Eseguire la migrazione da Dialogflow ES a Conversational Agents (Dialogflow CX)

Gli agenti Conversational Agents (Dialogflow CX) ti forniscono strumenti e controlli di conversazione più efficaci rispetto agli agenti Dialogflow ES. Se il tuo agente Dialogflow ES gestisce conversazioni complesse, dovresti prendere in considerazione la migrazione a Conversational Agents (Dialogflow CX).

Questa guida descrive come eseguire la migrazione di un agente da Dialogflow ES a Conversational Agents (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 qui sopra. Utilizzeremo questo feedback per migliorare questa guida nel tempo.

A livello generale, la procedura consigliata è un processo ibrido automatico/manuale. Utilizzerai uno strumento che legge alcuni dati dell'agente Dialogflow ES, li scrive nell'agente Conversational Agents (Dialogflow CX) e acquisisce un elenco di cose da fare. Poi, ricreate l'agente Conversational Agents (Dialogflow CX) completo utilizzando le best practice, l'elenco di cose da fare e i dati di cui è stata eseguita la migrazione dallo strumento.

Informazioni sugli agenti conversazionali (Dialogflow CX)

Prima di tentare questa migrazione, dovresti avere una solida conoscenza del funzionamento dei flussi di Conversational Agent (Dialogflow CX). Puoi iniziare da qui:

Ti consigliamo inoltre di leggere altri documenti di concetto che includono funzionalità che probabilmente ti serviranno nel nuovo agente. Concentrati su quanto segue:

Informazioni sulle differenze tra Dialogflow ES/Conversational Agents (Dialogflow CX)

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

Struttura e controllo del percorso di 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 associato un intento e, in un certo senso, ogni intento è un nodo per la conversazione.
  • Contesto 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 determinato numero di turni di conversazione, pertanto questo tipo di controllo può essere impreciso per conversazioni lunghe.

Conversational Agents (Dialogflow CX) fornisce una gerarchia di risorse di struttura e controlli più precisi sul percorso di conversazione:

  • Le pagine sono i nodi del grafico per la conversazione. Le conversazioni di Conversational Agents (Dialogflow CX) sono simili alle macchine a stati. In un determinato momento della conversazione, è attiva una pagina. In base agli input o agli eventi dell'utente finale, la conversazione potrebbe passare a un'altra pagina. È normale 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.
  • Gli handler di stato vengono utilizzati per controllare le transizioni e le risposte. Esistono tre tipi di gestori dello stato:
    • Percorso dell'intent: contiene un intent che deve essere associato, risposte facoltative e transizione di pagina facoltativa.
    • Percorso con condizioni: contiene una condizione che deve essere soddisfatta, risposte facoltative e transizione di pagina facoltativa.
    • Gestore eventi: contiene un nome di evento da richiamare, risposte facoltative e transizione di pagina facoltativa.
  • Ambito viene utilizzato per controllare se è possibile chiamare un gestore dello stato. La maggior parte degli handler è associata a una pagina o a un intero flusso. Se la pagina o il flusso associato è attivo, l'handler è nell'ambito e può essere chiamato. Un percorso dell'intent di Conversational Agents (Dialogflow CX) nell'ambito è simile a un intent di 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 relativa ai flussi della guida alla progettazione dell'agente.

Compilazione dei moduli

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

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

Conversational Agents (Dialogflow CX) utilizza il completamento dei moduli per raccogliere i parametri richiesti dall'utente finale:

  • Questi parametri sono associati a una pagina e vengono raccolti mentre la pagina è attiva.
  • Utilizzi i percorsi delle condizioni per le pagine per determinare che la compilazione del modulo è completata. Questi percorsi con condizioni di solito passano a un'altra pagina.
  • Puoi definire un prompt, nonché gestori di richieste di nuovo prompt per gestire in modo elegante più tentativi di raccolta di un valore.

Transizioni

Dialogflow ES passa automaticamente da un intent all'altro quando l'input utente finale corrisponde 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.

Gli agenti conversazionali (Dialogflow CX) passano da una pagina all'altra quando un gestore dello stato nell'ambito soddisfa i suoi requisiti e fornisce una destinazione di transizione. Utilizzando queste transizioni, puoi guidare in modo affidabile gli utenti finali nelle conversazioni. Esistono diversi modi per controllare queste transizioni:

  • La corrispondenza dell'intento può attivare un route intento.
  • La soddisfazione di una condizione può attivare un percorso di condizione.
  • L'invocazione di un evento può attivare un gestore di eventi.
  • I gestori di richieste ripetute possono causare una transizione quando l'utente finale non riesce a fornire un valore dopo più tentativi.
  • Puoi utilizzare 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 trovata una corrispondenza con un intent:

  • L'agente può selezionare un messaggio per la risposta da un elenco di possibili risposte.
  • Le risposte possono essere specifiche della piattaforma e possono utilizzare formati di risposta avanzati.
  • Le risposte possono essere basate su webhook.

Le risposte dell'agente di Conversational Agents (Dialogflow CX) vengono inviate all'utente finale quando viene chiamato il fulfillment. A differenza dell'implementazione di Dialogflow ES, che prevede sempre un webhook, l'implementazione di Conversational Agents (Dialogflow CX) può o meno prevedere l'uso di un webhook, a seconda che nella risorsa di implementazione sia configurato un webhook. Sia le risposte statiche che quelle dinamiche basate sulle risposte dei webhook vengono controllate dal completamento. Esistono diversi modi per creare le risposte dell'agente:

  • L'implementazione può essere fornita a qualsiasi tipo di gestore dello stato.
  • È possibile concatenare più risposte durante un turno di conversazione tramite la coda di risposta. In alcuni casi, questa funzionalità può semplificare il design dell'agente.
  • Conversational Agents (Dialogflow CX) non supporta le risposte predefinite specifiche della piattaforma. Tuttavia, fornisce più tipi di risposta, incluso un payload personalizzato che può essere utilizzato per le risposte specifiche della piattaforma.

Parametri

I parametri Dialogflow ES hanno le seguenti caratteristiche:

  • Definito solo nelle intenzioni.
  • Impostato in base all'input utente finale, agli eventi, ai webhook e alle chiamate API.
  • A cui viene fatto riferimento nelle risposte, nelle richieste di parametri, nel codice webhook e nei valori dei parametri:
    • 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 Conversational Agents (Dialogflow CX) hanno le seguenti caratteristiche:

  • Definiti negli intent e nei moduli di pagina.
  • I parametri di intent e modulo vengono propagati ai parametri di sessione, dove sono disponibili per il riferimento per la durata della sessione.
  • Impostato dall'input utente finale, dai webhook, dalla preimpostazione del parametro di adempimento e dalle chiamate API.
  • A cui viene fatto riferimento nelle risposte, nelle richieste di parametri, negli handler di richieste di nuovo prompt, nelle preimpostazioni dei parametri e nel codice webhook:
    • Il formato di riferimento è $session.params.parameter-id per i parametri della sessione e $intent.params.parameter-id per i parametri dell'intent.
    • I riferimenti ai parametri di intent supportano la sintassi dei suffissi .original e .resolved. I parametri sessione non supportano questa sintassi.

Entità di sistema

Dialogflow ES supporta molte entità di sistema.

Conversational Agents (Dialogflow CX) supporta molte delle stesse entità di sistema, ma ci sono alcune differenze. Durante la migrazione, verifica che le entità di sistema che utilizzi in Dialogflow ES siano supportate anche da Conversational Agents (Dialogflow CX) per la stessa lingua. In caso contrario, devi creare entità personalizzate per questi.

Eventi

Gli eventi Dialogflow ES hanno le seguenti caratteristiche:

  • Può essere richiamato da chiamate API o webhook per trovare una corrispondenza con un'intenzione.
  • Può impostare i parametri.
  • Un numero limitato di eventi viene invocato dalle piattaforme di integrazione.

Gli eventi di Conversational Agents (Dialogflow CX) hanno le seguenti caratteristiche:

  • Può essere richiamato da chiamate API o webhook per chiamare un gestore eventi.
  • Impossibile impostare i parametri.
  • Molti eventi integrati possono essere utilizzati per gestire la mancanza di input utente dell'utente finale, input utente finale non riconosciuti, parametri non convalidati da un webhook ed errori webhook.
  • Le invocazioni possono essere controllate dalle stesse regole di ambito di altri gestori dello stato.

Intent integrati

Dialogflow ES supporta i seguenti intent integrati:

Di seguito viene descritto il supporto di Conversational Agents (Dialogflow CX) per gli intent integrati:

  • Gli intent di benvenuto sono supportati.
  • Non vengono forniti intent di riserva. Utilizza gli eventi no-match nei gestori degli eventi.
  • Per gli esempi negativi, utilizza l'intenzione negativa predefinita.
  • Gli intent di follow-up predefiniti non sono forniti. Devi creare questi intent in base alle esigenze del tuo agente. Ad esempio, probabilmente dovrai creare un'intenzione per gestire le risposte negative a una domanda dell'agente ("no", "no grazie", "no, non ho" e così via). Gli intent di Conversational Agents (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 utilizzante il webhook.
  • Non è disponibile il supporto integrato per la gestione degli errori webhook.
  • Le azioni o i nomi degli intent vengono utilizzati dai webhook per determinare da dove è stata chiamata l'azione nell'agente.
  • La console fornisce l'editor in linea.

I webhook di Conversational Agents (Dialogflow CX) hanno le seguenti caratteristiche:

  • Puoi configurare più servizi webhook per l'agente.
  • Ogni adempimento può specificare facoltativamente una chiamata webhook.
  • È disponibile il supporto integrato per la gestione degli errori dei webhook.
  • Un webhook di adempimento di Conversational Agents (Dialogflow CX) contiene un tag. Questo tag è simile a un'azione Dialogflow ES, ma viene utilizzato solo quando vengono chiamati gli 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 Functions, ma ci sono molte opzioni.

Quando esegui la migrazione a Conversational Agents (Dialogflow CX), dovrai modificare il codice webhook, poiché le proprietà di richiesta e risposta sono diverse.

Integrazioni

Le integrazioni di Dialogflow ES e le integrazioni di Conversational Agents (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 Conversational Agents (Dialogflow CX), potrebbe essere necessario cambiare piattaforma o implementare l'integrazione autonomamente.

Altre funzionalità solo per Conversational Agents (Dialogflow CX)

Esistono molte altre funzionalità fornite solo da Conversational Agents (Dialogflow CX). Ti consigliamo di utilizzare queste funzionalità durante la migrazione. Ad esempio:

Best practice

Prima di eseguire la migrazione, familiarizati con le best practice per la progettazione di agenti di Conversational Agents (Dialogflow CX). Molte di queste best practice di Conversational Agents (Dialogflow CX) sono simili alle best practice di Dialogflow ES, ma alcune sono uniche per Conversational Agents (Dialogflow CX).

Informazioni sullo strumento di migrazione

Lo strumento di migrazione copia la maggior parte dei dati di Dialogflow ES nell'agente Conversational Agents (Dialogflow CX) e scrive in un file TODO con un elenco di elementi di cui deve essere eseguita la migrazione manuale. Lo strumento copia solo i tipi di entità personalizzate e le frasi di addestramento dell'intenzione. Ti consigliamo di personalizzare questo strumento in base alle tue esigenze specifiche.

Codice dello strumento di migrazione

Ecco il codice dello strumento. Ti consigliamo di esaminare il codice di questo strumento per capire che cosa fa. Ti consigliamo di modificare questo codice per gestire situazioni specifiche nell'agente. Nei passaggi riportati di seguito, 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 tipi di entità di Conversational Agents (Dialogflow CX) sono molto simili, quindi sono i tipi di dati più semplici per la migrazione. Lo strumento copia semplicemente i tipi di entità così come sono.

Migrazione degli intent con lo strumento

Gli intent di Dialogflow ES e gli intent di Conversational Agents (Dialogflow CX) sono molto diversi.

Gli intent di Dialogflow ES vengono utilizzati come componenti 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.

Conversational Agents (Dialogflow CX) ha spostato la maggior parte di questi dati in altre risorse. Gli intent di Conversational Agents (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 degli intent negli intent di Conversational Agents (Dialogflow CX).

Limitazioni dello strumento di migrazione

Lo strumento di migrazione non supporta quanto segue:

  • Mega agenti: lo strumento non può leggere da più agenti secondari, ma puoi richiamarlo più volte per ogni agente secondario.
  • Agenti multilingue: devi modificare lo strumento per creare frasi di addestramento e voci di entità multilingue.
  • Verifica delle entità di sistema per le lingue diverse dall'inglese: lo strumento crea elementi TODO quando trova entità di sistema non supportate dagli agenti conversazionali (Dialogflow CX), supponendo 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 della migrazione

Le sottosezioni seguenti descrivono i passaggi di migrazione da seguire. Non è necessario seguire questi passaggi manuali in ordine, e potrebbe anche essere necessario eseguirli 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 ricostruire l'agente Conversational Agents (Dialogflow CX). Dovrai ancora eseguire una buona quantità di lavoro di migrazione, ma la maggior parte dei dati inseriti manualmente sarà presente nell'agente di conversazione (Dialogflow CX) e nel file TODO.

Creare l'agente Conversational Agents (Dialogflow CX)

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

Esegui lo strumento di migrazione

Per eseguire lo strumento, svolgi i seguenti passaggi:

  1. Se non lo 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 in questa directory denominato main.go.
  4. Modifica il codice, se necessario per la tua richiesta.
  5. Crea un modulo Go in questa directory. Ad esempio:

    go mod init migrate
    
  6. Installa le librerie client Go di Dialogflow ES 2.0 e Conversational Agents (Dialogflow CX) 3.0:

    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 in un 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 relativi allo strumento di migrazione

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

Errore Risoluzione
Errore RPC: 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 modo incoerente con le frasi di addestramento. Per risolvere il problema, rinomina il parametro Dialogflow ES dalla console, controlla 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à dall'agente Conversational Agents (Dialogflow CX) prima di eseguire di nuovo lo strumento di migrazione.

Spostare i dati sugli intent di Dialogflow ES in Conversational Agents (Dialogflow CX)

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

Un'intenzione Dialogflow ES potrebbe richiedere una pagina di Conversational Agents (Dialogflow CX) corrispondente, un'intenzione di Conversational Agents (Dialogflow CX) corrispondente o entrambe.

Se viene utilizzata una corrispondenza dell'intent Dialogflow ES per passare dalla conversazione da un determinato nodo di conversazione a un altro, dovresti avere due pagine nell'agente relative 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 avere messaggi di adempimento di Conversational Agents (Dialogflow CX) simili alle risposte dell'intent di Dialogflow ES. In questa pagina potresti avere molti percorsi di intent. Mentre la pagina originale è attiva, questi percorsi di intent possono indirizzare la conversazione a molti percorsi possibili. Molti intent di Dialogflow ES condivideranno la stessa pagina originale di Conversational Agents (Dialogflow CX).
  • La pagina successiva, che è il target di transizione per il percorso dell'intent nella pagina originale: l'elaborazione dell'entrata di Conversational Agents (Dialogflow CX) per la pagina successiva potrebbe avere messaggi di elaborazione di Conversational Agents (Dialogflow CX) simili alle risposte dell'intent di Dialogflow ES.

Se un'intenzione Dialogflow ES contiene parametri obbligatori, devi creare una pagina di Conversational Agents (Dialogflow CX) corrispondente con gli stessi parametri in un modulo.

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

Gli intent di riserva e di follow-up predefiniti non esistono in Conversational Agents (Dialogflow CX). Consulta gli intent integrati.

La tabella seguente descrive come mappare dati specifici sull'intenzione da Dialogflow ES alle risorse di Conversational Agents (Dialogflow CX):

Dati sugli intent di Dialogflow ES Dati di Conversational Agents (Dialogflow CX) corrispondenti Azione richiesta
Frasi di addestramento Frasi di addestramento per gli intent Migrazione eseguita per strumento. Lo strumento controlla il supporto delle entità di sistema e crea elementi TODO per le entità di sistema non supportate.
Risposte dell'agente Messaggi di risposta all'evasione Consulta 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 evasione degli ordini Consulta gli webhook.
Eventi Gestori di eventi a livello di flusso o di pagina Vedi eventi.
Azioni Tag webhook di evasione degli ordini Consulta gli webhook.
Parametri Parametri dell'intent e/o parametri del modulo della pagina Migrazione ai parametri dell'intent per strumento. Se i parametri sono obbligatori, lo strumento crea elementi TODO per la possibile migrazione a una pagina. Consulta la sezione Parametri.
Prompt dei parametri Prompt per i parametri del modulo della pagina Vedi Compilazione dei moduli.

Creare 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 vada spesso 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

È meglio testare l'agente con il simulatore durante l'iterazione delle modifiche. Pertanto, all'inizio dovresti concentrarti sui percorsi di conversazione di base e testare man mano che apporti modifiche. Una volta che hai capito come funzionano, passa a percorsi di conversazione più dettagliati.

Gestori di stato a livello di flusso e a livello di pagina

Quando crei gestori dello stato, 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 è nell'ambito solo quando la pagina specifica è attiva. Gli handler a livello di flusso sono simili agli intent di Dialogflow ES senza contesto di input. Gli handler 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 Conversational Agents (Dialogflow CX). Consulta la sezione sui webhook.

Connettori di conoscenza

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

Impostazioni dell'agente

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

Utilizzare 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 del 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 di progettazione, dovrai aggiornare questo codice per utilizzare l'API Agenti conversazionali (Dialogflow CX). Se utilizzi le chiamate di rilevamento dell'intenzione solo in fase di esecuzione, questo aggiornamento dovrebbe essere abbastanza semplice.

Integrazioni

Se il tuo agente utilizza le integrazioni, consulta la sezione relativa alle integrazioni e apporta le modifiche necessarie.

Le seguenti sottosezioni descrivono i passaggi consigliati per la migrazione.

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 Conversational Agents (Dialogflow CX) e verificare che il comportamento sia simile o migliorato.

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

Ambienti

Esamina i tuoi ambienti Dialogflow ES e aggiorna i tuoi ambienti Conversational Agents (Dialogflow CX) in base alle necessità.