Migrar do Dialogflow ES para agentes de conversação (Dialogflow CX)

Os agentes de conversação (Dialogflow CX) oferecem controles e ferramentas de conversação mais eficientes do que os agentes do Dialogflow ES. Se o agente do Dialogflow ES processa conversas complexas, considere migrar para os agentes de conversação (Dialogflow CX).

Este guia descreve como migrar um agente do Dialogflow ES para agentes de conversação (Dialogflow CX). Esses dois tipos de agentes têm muitas diferenças fundamentais, portanto, não há uma maneira direta de realizar essa migração.

Se você usar este guia para uma migração, envie feedback positivo ou negativo clicando no botão Enviar feedback acima. Vamos usar esse feedback para melhorar este guia com o tempo.

De modo geral, o processo recomendado é um processo híbrido automatizado/manual. Você vai usar uma ferramenta que lê alguns dos dados do agente do Dialogflow ES, grava esses dados no agente de agentes de conversação (Dialogflow CX) e captura uma lista de tarefas. Em seguida, recrie o agente de agentes de conversação (Dialogflow CX) completo usando as práticas recomendadas, a lista de tarefas pendentes e os dados migrados pela ferramenta.

Entender os agentes de conversação (Dialogflow CX)

Antes de tentar essa migração, você precisa entender bem como os fluxos de agentes de conversação (Dialogflow CX) funcionam. Comece aqui:

Também leia outros documentos de conceito que tenham recursos que você provavelmente vai precisar no novo agente. Concentre-se nos seguintes aspectos:

Entender as diferenças entre o Dialogflow ES/agentes de conversação (Dialogflow CX)

Esta seção lista as diferenças mais importantes entre o Dialogflow ES e os agentes de conversação (Dialogflow CX). Ao realizar etapas de migração manual mais tarde, consulte esta seção para receber orientações.

Estrutura e controle do caminho da conversa

O Dialogflow ES oferece o seguinte para o controle de estrutura e caminho de conversa:

  • As intenções são usadas como os elementos básicos do agente. Em qualquer momento da conversa, uma intent é correspondida, e, em certo sentido, cada intent é um nó da conversa.
  • O contexto é usado para controlar a conversa. O contexto é usado para controlar quais intents podem ser correspondidas a qualquer momento. O contexto expira após um determinado número de turnos de conversa, portanto, esse tipo de controle pode ser impreciso para conversas longas.

Os agentes de conversação (Dialogflow CX) oferecem uma hierarquia de recursos de estrutura e controles mais precisos sobre o caminho da conversa:

  • Páginas são nós de gráfico da conversa. As conversas dos agentes de conversação (Dialogflow CX) são semelhantes a máquinas de estado. Em qualquer ponto da conversa, uma página fica ativa. Com base na entrada do usuário final ou em eventos, a conversa pode ser transferida para outra página. É comum que uma página permaneça ativa por várias rodadas de conversa.
  • Os fluxos são grupos de páginas relacionadas. Cada fluxo precisa processar um tópico de conversa de alto nível.
  • Os gerenciadores de estado são usados para controlar transições e respostas. Há três tipos de manipuladores de estado:
    • Rota de intent: contém uma intent que precisa ser correspondida, respostas opcionais e transição de página opcional.
    • Rota de condição: contém uma condição que precisa ser atendida, respostas opcionais e transição de página opcional.
    • Manipulador de eventos: contém um nome de evento que precisa ser invocado, respostas opcionais e transição de página opcional.
  • O escopo é usado para controlar se um gerenciador de estado pode ser chamado. A maioria dos processadores está associada a uma página ou a um fluxo inteiro. Se a página ou o fluxo associado estiver ativo, o gerenciador estará no escopo e poderá ser chamado. Uma rota de intent de agentes de conversação (Dialogflow CX) no escopo é semelhante a uma intent do Dialogflow ES com um contexto de entrada ativo.

Ao projetar os fluxos e as páginas do seu agente, entenda os conselhos da seção de fluxo do guia de design do agente.

Preenchimento de formulário

O Dialogflow ES usa o preenchimento de slot para coletar os parâmetros necessários do usuário final:

  • Esses parâmetros são marcados como obrigatórios.
  • A intent continua sendo correspondida até que todos os parâmetros obrigatórios sejam coletados.
  • Você pode definir uma solicitação para que o usuário final forneça um valor.

Os agentes de conversação (Dialogflow CX) usam o preenchimento de formulários para coletar os parâmetros necessários do usuário final:

  • Esses parâmetros são associados a uma página e são coletados enquanto ela está ativa.
  • Você usa rotas de condição para páginas para determinar se o preenchimento do formulário foi concluído. Essas rotas de condição geralmente fazem a transição para outra página.
  • É possível definir uma solicitação e gerenciadores de nova solicitação para processar várias tentativas de coletar um valor.

Transições

O Dialogflow ES faz a transição automaticamente de uma intent para a próxima quando a entrada do usuário final é associada a uma intent. Essa correspondência só pode ocorrer para intents sem contexto de entrada ou com um contexto de entrada ativo.

Os agentes de conversação (Dialogflow CX) fazem a transição de uma página para outra quando um manipulador de estado no escopo atende aos requisitos e fornece um destino de transição. Usando essas transições, é possível guiar os usuários finais com segurança durante as conversas. Há várias maneiras de controlar essas transições:

  • A correspondência de intent pode acionar uma rota de intent.
  • A satisfação de uma condição pode acionar uma rota de condição.
  • A invocação de um evento pode acionar um manipulador de eventos.
  • Os gerenciadores de nova solicitação podem causar uma transição quando o usuário final não fornece um valor após várias tentativas.
  • Você pode usar alvos de transição simbólica para alvos de transição.

Respostas do agente

As respostas do agente do Dialogflow ES são enviadas ao usuário final quando uma intent é correspondida:

  • O agente pode selecionar uma mensagem para a resposta em uma lista de respostas possíveis.
  • As respostas podem ser específicas da plataforma, que podem usar formatos de resposta avançados.
  • As respostas podem ser geradas por webhooks.

As respostas dos agentes de conversação (Dialogflow CX) são enviadas ao usuário final quando a execução é chamada. Ao contrário do fulfillment do Dialogflow ES, que sempre envolve um webhook, o fulfillment dos agentes de conversação (Dialogflow CX) pode ou não envolver a chamada de um webhook, dependendo se o recurso de fulfillment tem um webhook configurado. As respostas estáticas e dinâmicas com base nas respostas de webhook são controladas pelo fulfillment. Há várias maneiras de criar respostas do agente:

  • O fulfillment pode ser fornecido para qualquer tipo de gerenciador de estado.
  • Várias respostas podem ser concatenadas durante uma rodada de conversa pela fila de respostas. Esse recurso pode simplificar o design do agente em alguns casos.
  • Os agentes de conversação (Dialogflow CX) não oferecem suporte a respostas integradas específicas da plataforma. No entanto, ele oferece vários tipos de resposta, incluindo um payload personalizado que pode ser usado para respostas específicas da plataforma.

Parâmetros

Os parâmetros do Dialogflow ES têm as seguintes características:

  • Definido apenas em intents.
  • É definido pela entrada do usuário final, eventos, webhooks e chamadas de API.
  • Referenciado em respostas, prompts de parâmetro, código de webhook e valores de parâmetro:
    • O formato de referência básico é $parameter-name.
    • As referências oferecem suporte à sintaxe de sufixo .original, .partial e .recent.
    • As referências podem especificar o contexto ativo: #context-name.parameter-name.
    • As referências podem especificar parâmetros de evento: #event-name.parameter-name.

Os parâmetros de agentes de conversação (Dialogflow CX) têm as seguintes características:

  • Definido em intents e formulários de página.
  • Os parâmetros de intent e de formulário são propagados para parâmetros de sessão, onde ficam disponíveis para referência durante a sessão.
  • Definido pela entrada do usuário final, webhooks, predefinição de parâmetro de fulfillment e chamadas de API.
  • Referenciado em respostas, solicitações de parâmetros, gerenciadores de nova solicitação, predefinições de parâmetros e código de webhook:
    • O formato de referência é $session.params.parameter-id para parâmetros de sessão e $intent.params.parameter-id para parâmetros de intent.
    • As referências de parâmetros de intent oferecem suporte à sintaxe de sufixo .original e .resolved. Os parâmetros de sessão não são compatíveis com essa sintaxe.

Entidades do sistema

O Dialogflow ES oferece suporte a muitas entidades do sistema.

Os agentes de conversação (Dialogflow CX) oferecem suporte a muitas das mesmas entidades do sistema, mas há algumas diferenças. Ao migrar, verifique se as entidades do sistema que você está usando no Dialogflow ES também são compatíveis com os agentes de conversação (Dialogflow CX) para o mesmo idioma. Caso contrário, crie entidades personalizadas para elas.

Eventos

Os eventos do Dialogflow ES têm as seguintes características:

  • Pode ser invocado por chamadas de API ou webhooks para corresponder a uma intent.
  • Pode definir parâmetros.
  • Um pequeno número de eventos é invocado pelas plataformas de integração.

Os eventos de agentes de conversação (Dialogflow CX) têm as seguintes características:

  • Pode ser invocado por chamadas de API ou webhooks para chamar um manipulador de eventos.
  • Não é possível definir parâmetros.
  • Muitos eventos integrados podem ser usados para processar a falta de entrada do usuário final, entrada do usuário final não reconhecida, parâmetros invalidados por um webhook e erros de webhook.
  • As invocações podem ser controladas pelas mesmas regras de escopo que outros gerenciadores de estado.

Intents incorporadas

O Dialogflow ES oferece suporte às seguintes intenções integradas:

Confira a seguir o suporte dos agentes de conversação (Dialogflow CX) para intents integradas:

  • Intents de boas-vindas são compatíveis.
  • As intents substitutas não são fornecidas. Use os eventos sem correspondência em manipuladores de eventos.
  • Para exemplos negativos, use a intent negativa padrão.
  • Não são fornecidos intents de acompanhamento predefinidos. Você precisa criar essas intents conforme exigido pelo agente. Por exemplo, você provavelmente precisará criar uma intent para processar respostas negativas a uma pergunta do agente ("não", "não, obrigado", "não, não quero" e assim por diante). As intenções de agentes de conversação (Dialogflow CX) são reutilizáveis em todo o agente, então você só precisa defini-las uma vez. Usar rotas de intent diferentes para essas intent comuns, em diferentes escopos, dá a você um controle muito melhor sobre a conversa.

Webhooks

Os webhooks do Dialogflow ES têm as seguintes características:

  • É possível configurar um serviço de webhook para o agente.
  • Cada intent pode ser marcada como usando o webhook.
  • Não há suporte integrado para processar erros de webhook.
  • As ações ou os nomes de intent são usados pelos webhooks para determinar de onde ele foi chamado no agente.
  • O console oferece o editor inline.

Os webhooks de agentes de conversação (Dialogflow CX) têm as seguintes características:

  • É possível configurar vários serviços de webhook para o agente.
  • Cada fulfillment pode especificar uma chamada de webhook.
  • Há suporte integrado para tratamento de erros de webhook.
  • Um webhook de fulfillment de agentes de conversação (Dialogflow CX) contém uma tag. Essa tag é semelhante a uma ação do Dialogflow ES, mas é usada apenas para chamar webhooks. O serviço de webhook pode usar essas tags para determinar de onde ele foi chamado no agente.
  • O console não tem um editor de código de webhook integrado. É comum usar o Cloud Functions, mas há muitas opções.

Ao migrar para agentes de conversação (Dialogflow CX), você vai precisar mudar o código do webhook, porque as propriedades de solicitação e resposta são diferentes.

Integrações

As integrações do Dialogflow ES e as integrações de agentes de conversação (Dialogflow CX) são compatíveis com diferentes plataformas. Para plataformas com suporte para os dois tipos de agentes, pode haver diferenças na configuração.

Se a integração do Dialogflow ES que você estava usando não tiver suporte a agentes de conversação (Dialogflow CX), talvez seja necessário mudar de plataforma ou implementar a integração por conta própria.

Mais recursos exclusivos para agentes de conversação (Dialogflow CX)

Há muitos outros recursos fornecidos apenas por agentes de conversação (Dialogflow CX). Considere usar esses recursos durante a migração. Exemplo:

Práticas recomendadas

Antes de migrar, conheça as práticas recomendadas de design de agentes de IA de conversação (Dialogflow CX). Muitas dessas práticas recomendadas para agentes de conversação (Dialogflow CX) são semelhantes às práticas recomendadas do Dialogflow ES, mas algumas são exclusivas para agentes de conversação (Dialogflow CX).

Sobre a ferramenta de migração

A ferramenta de migração copia a maior parte dos dados do Dialogflow ES para seus agentes de conversação (Dialogflow CX) e grava em um arquivo TODO com uma lista de itens que precisam ser migrados manualmente. A ferramenta só copia tipos de entidades personalizadas e frases de treinamento de intenção. Considere personalizar essa ferramenta para atender às suas necessidades específicas.

Código da ferramenta de migração

Confira o código da ferramenta. Revise o código dessa ferramenta para entender o que ela faz. Talvez seja necessário mudar esse código para lidar com situações específicas no agente. Nas etapas abaixo, você vai executar essa ferramenta.

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

Migração de ferramentas de tipos de entidade

Os tipos de entidade do Dialogflow ES e os tipos de entidade dos agentes de conversação (Dialogflow CX) são muito semelhantes, portanto, são os tipos de dados mais fáceis de migrar. A ferramenta simplesmente copia os tipos de entidade como estão.

Migração de ferramentas de intents

As intenções do Dialogflow ES e dos agentes de conversação (Dialogflow CX) são muito diferentes.

As intents do Dialogflow ES são usadas como elementos básicos do agente. Elas contêm frases de treinamento, respostas, contexto para controle de conversação, configurações de webhook, eventos, ações e parâmetros de preenchimento de slot.

Os agentes de conversação (Dialogflow CX) transferiram a maior parte desses dados para outros recursos. As intents dos agentes de conversação (Dialogflow CX) têm apenas frases e parâmetros de treinamento, o que as torna reutilizáveis em todo o agente. A ferramenta só copia esses dois tipos de dados de intenção para seus agentes de conversação (Dialogflow CX).

Limitações da ferramenta de migração

A ferramenta de migração não é compatível com o seguinte:

  • Megaagentes: a ferramenta não pode ler de vários subagentes, mas você pode chamar a ferramenta várias vezes em cada subagente.
  • Agentes multilíngues: modifique a ferramenta para criar frases de treinamento e entradas de entidade multilíngues.
  • Verificação de entidade do sistema para idiomas que não são em inglês: a ferramenta cria itens de pendentes quando encontra entidades do sistema que não têm suporte de agentes de conversação (Dialogflow CX), considerando que o inglês é o idioma padrão e que ele usa uma região dos EUA. A compatibilidade de entidades do sistema varia de acordo com o idioma e a região. Para outros idiomas e regiões, modifique a ferramenta para realizar essa verificação.

Etapas essenciais da migração

As subseções a seguir descrevem as etapas de migração a serem seguidas. Não é necessário seguir essas etapas manuais em ordem. Talvez seja necessário realizá-las simultaneamente ou em uma ordem diferente. Leia as etapas e comece a planejar as mudanças antes de fazer alterações.

Depois de executar a ferramenta de migração, é possível recriar o agente de agentes de conversação (Dialogflow CX). Você ainda terá uma boa quantidade de trabalho de migração a fazer, mas a maior parte dos dados inseridos manualmente estará presente nos agentes de conversação (Dialogflow CX) e no arquivo TODO.

Criar agentes de conversação (Dialogflow CX)

Se ainda não tiver feito isso, crie seus agentes de conversação (Dialogflow CX). Use o mesmo idioma padrão do agente do Dialogflow ES.

Executar a ferramenta de migração

Siga estas etapas para executar a ferramenta:

  1. Instale o Go na sua máquina, caso ainda não tenha feito isso.
  2. Crie um diretório para o código da ferramenta chamado migrate.
  3. Copie o código da ferramenta acima para um arquivo nesse diretório chamado main.go.
  4. Modifique o código se necessário para seu caso.
  5. Crie um módulo Go neste diretório. Exemplo:

    go mod init migrate
    
  6. Instale as bibliotecas de cliente do Dialogflow ES V2 e dos agentes de conversação (Dialogflow CX) V3 do Go:

    go get cloud.google.com/go/dialogflow/apiv2
    go get cloud.google.com/go/dialogflow/cx/apiv3
    
  7. Verifique se você configurou a autenticação da biblioteca de cliente.

  8. Execute a ferramenta e salve a saída em um arquivo:

    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
    

Solução de problemas da ferramenta de migração

Se você encontrar erros ao executar a ferramenta, verifique o seguinte:

Erro Resolução
Erro de RPC: uma parte da frase de treinamento menciona um parâmetro não definido para a intent. Isso pode acontecer se você já tiver usado a API Dialogflow ES para criar parâmetros de intent de forma inconsistente com as frases de treinamento. Para corrigir isso, renomeie o parâmetro do Dialogflow ES no console, verifique se as frases de treinamento estão usando o parâmetro corretamente e clique em "Salvar". Isso também pode acontecer se as frases de treinamento fizerem referência a parâmetros inexistentes.

Depois de corrigir os erros, você vai precisar limpar os agentes de agentes de conversação (Dialogflow CX) de intents e entidades antes de executar a ferramenta de migração novamente.

Como mover dados de intent do Dialogflow ES para agentes de conversação (Dialogflow CX)

A ferramenta migra frases e parâmetros de treinamento de intenção para agentes de conversação (Dialogflow CX), mas há muitos outros campos de intenção do Dialogflow ES para migrar manualmente.

Uma intent do Dialogflow ES pode precisar de uma página de agentes de conversação (Dialogflow CX) correspondente, uma intent de agentes de conversação (Dialogflow CX) correspondente ou ambos.

Se uma correspondência de intent do Dialogflow ES for usada para fazer a transição da conversa de um nó de conversa específico para outro, você terá duas páginas no seu agente relacionadas a essa intent:

  • A página original que contém a rota de intent, que vai fazer a transição para a próxima página: a rota de intent na página original pode ter mensagens de fulfillment de agentes de conversação (Dialogflow CX) semelhantes às respostas de intent do Dialogflow ES. Você pode ter muitas rotas de intent nesta página. Enquanto a página original está ativa, essas rotas de intent podem fazer a transição da conversa para muitos caminhos possíveis. Muitas intenções do Dialogflow ES vão compartilhar a mesma página original dos agentes de conversação (Dialogflow CX).
  • A próxima página, que é o destino da transição para a rota de intent na página original: o fulfillment de entrada de agentes de conversação (Dialogflow CX) para a próxima página pode ter mensagens de fulfillment de agentes de conversação (Dialogflow CX) semelhantes às respostas de intent do Dialogflow ES.

Se uma intent do Dialogflow ES tiver parâmetros obrigatórios, crie uma página de agentes de conversação (Dialogflow CX) correspondente com os mesmos parâmetros em um formulário.

É comum que uma intent de agentes de conversação (Dialogflow CX) e uma página de agentes de conversação (Dialogflow CX) compartilhem a mesma lista de parâmetros, o que significa que uma única intent do Dialogflow ES tem uma página de agentes de conversação (Dialogflow CX) e uma intent de agentes de conversação (Dialogflow CX) correspondentes. Quando uma intent de agentes de conversação (Dialogflow CX) com parâmetros em uma rota de intent é correspondida, a conversa geralmente transita para uma página com os mesmos parâmetros. Os parâmetros extraídos da correspondência de intent são propagados para parâmetros de sessão, que estão disponíveis para preencher parcialmente ou totalmente os parâmetros do formulário da página.

As intents de fallback e de acompanhamento predefinidas não existem nos agentes de conversação (Dialogflow CX). Consulte intents integradas.

A tabela a seguir descreve como mapear dados de intent específicos do Dialogflow ES para recursos de agentes de conversação (Dialogflow CX):

Dados de intent do Dialogflow ES Dados correspondentes dos agentes de conversação (Dialogflow CX) Ação necessária
Frases de treinamento Frases de treinamento de intent Migrado por ferramenta. A ferramenta verifica o suporte de entidade do sistema e cria itens de tarefas para entidades do sistema sem suporte.
Respostas do agente Mensagens de resposta de fulfillment Consulte Respostas do agente.
Contexto para o controle de conversas Nenhum Consulte Estrutura e controle do caminho da conversa.
Configuração do webhook Configuração do webhook de fulfillment Consulte webhooks.
Eventos Manipuladores de eventos no nível do fluxo ou da página Consulte eventos.
Ações Tags de webhook de fulfillment Consulte webhooks.
Parâmetros Parâmetros de intent e/ou parâmetros do formulário da página Migrado para parâmetros de intent por ferramenta. Se os parâmetros forem necessários, a ferramenta vai criar itens de tarefa para migrar para uma página. Consulte parâmetros.
Solicitações de parâmetro Prompts de parâmetro do formulário da página Consulte Preenchimento de formulário.

Criar fluxos

Crie um fluxo para cada tópico de conversa de alto nível. Os tópicos de cada fluxo precisam ser distintos, para que a conversa não mude frequentemente entre os fluxos.

Se você estava usando um mega-agente, cada subagente precisa se tornar um ou mais fluxos.

Comece com caminhos de conversa básicos

É melhor testar seu agente com o simulador enquanto itera as mudanças. Portanto, inicialmente, concentre-se nos caminhos de conversa básicos no início da conversa e teste conforme faz as mudanças. Depois que eles estiverem funcionando, vá para caminhos de conversa mais detalhados.

Manipuladores de estado no nível do fluxo e no nível da página

Ao criar processadores de estado, considere se eles precisam ser aplicados no nível do fluxo ou da página. Um gerenciador no nível do fluxo está no escopo sempre que o fluxo (e, portanto, qualquer página dentro dele) está ativo. Um manipulador no nível da página só está no escopo quando a página específica está ativa. Os gerenciadores no nível do fluxo são semelhantes às intents do Dialogflow ES sem contexto de entrada. Os manipuladores no nível da página são semelhantes às intents do Dialogflow ES com contexto de entrada.

Código do webhook

As propriedades de solicitação e resposta do webhook são diferentes para agentes de conversação (Dialogflow CX). Consulte a seção de webhooks.

Conectores de conhecimento

Os agentes de conversação (Dialogflow CX) ainda não oferecem suporte a conectores de conhecimento. Você vai precisar implementar essas ações como intents normais ou esperar até que os agentes de conversação (Dialogflow CX) ofereçam suporte a conectores de conhecimento.

Configurações do agente

Revise as configurações do agente do Dialogflow ES e ajuste as configurações dos agentes de conversação (Dialogflow CX) conforme necessário.

Usar o arquivo TODO

A ferramenta de migração gera um arquivo CSV. Os itens desta lista se concentram em partes específicas dos dados que podem precisar de atenção. Importe este arquivo para uma planilha. Resolva cada item na planilha, usando uma coluna para marcar a conclusão.

Migração do uso da API

Se o sistema usar a API Dialogflow ES para chamadas de execução ou de design, você vai precisar atualizar esse código para usar a API de agentes de conversação (Dialogflow CX). Se você só usa as chamadas de detecção de intent no momento da execução, essa atualização é bastante simples.

Integrações

Se o agente usa integrações, consulte a seção de integrações e faça as mudanças necessárias.

As subseções a seguir descrevem as etapas de migração recomendadas.

Validação

Use a validação do agente para verificar se ele segue as práticas recomendadas.

Teste

Ao realizar as etapas de migração manual acima, teste seu agente com o simulador. Quando o agente parecer estar funcionando, compare as conversas entre os agentes do Dialogflow ES e do Conversational Agents (Dialogflow CX) e verifique se o comportamento é semelhante ou melhorado.

Ao testar essas conversas com o simulador, crie casos de teste para evitar regressões futuras.

Ambientes

Analise seus ambientes do Dialogflow ES e atualize seus ambientes de agentes de conversação (Dialogflow CX) conforme necessário.