Los agentes de Dialogflow CX te proporcionan herramientas y controles de conversación más potentes que los agentes de Dialogflow ES. Si tu agente de Dialogflow ES controla conversaciones complejas, deberías considerar migrar a Dialogflow CX.
En esta guía, se describe cómo migrar un agente de Dialogflow ES a Dialogflow CX. Estos dos tipos de agentes tienen muchas diferencias fundamentales, por lo que no hay una forma directa de realizar esta migración.
Si usas esta guía para una migración, proporciona comentarios positivos o negativos haciendo clic en el botón Enviar comentarios que aparece más arriba. Usaremos estos comentarios para mejorar esta guía con el tiempo.
En términos generales, el proceso recomendado es un proceso híbrido automatizado y manual. Usarás una herramienta que lee algunos de los datos de tu agente de Dialogflow ES, escribe esos datos en tu agente de Dialogflow CX y captura una lista de tareas pendientes. Luego, vuelve a crear tu agente de Dialogflow CX completo con las prácticas recomendadas, la lista de tareas pendientes y los datos que migró la herramienta.
Comprende Dialogflow CX
Antes de intentar esta migración, debes comprender bien cómo funcionan los flujos de Dialogflow CX. Puedes comenzar aquí:
También debes leer los documentos de conceptos adicionales que tienen funciones que probablemente necesites en tu agente nuevo. Concéntrate en lo siguiente:
- Descripción general de Console
- Agentes
- Flows
- Páginas
- Controladores de estado
- Intents
- Parámetros
- Entregas
- Webhooks
Comprender las diferencias entre Dialogflow ES y Dialogflow CX
En esta sección, se enumeran las diferencias más importantes entre Dialogflow ES y Dialogflow CX. Cuando realices los pasos de migración manual más adelante, deberás consultar esta sección para obtener orientación.
Control de la estructura y la ruta de conversación
Dialogflow ES proporciona lo siguiente para controlar la estructura y la ruta de conversación:
- Los intents se usan como los componentes básicos del agente. En cualquier punto de la conversación, se establece una coincidencia con un intent y, en cierto sentido, cada intent es un nodo de la conversación.
- El contexto se usa para controlar la conversación. El contexto se usa para controlar qué intents pueden coincidir en un momento determinado. El contexto vence después de una cierta cantidad de turnos de conversación, por lo que este tipo de control puede ser impreciso para conversaciones largas.
Dialogflow CX proporciona una jerarquía de recursos de estructura y controles más precisos sobre la ruta de conversación:
- Las páginas son nodos de grafo para la conversación. Las conversaciones de Dialogflow CX son similares a las máquinas de estados. En cualquier momento de la conversación, hay una página activa. Según la entrada o los eventos del usuario final, la conversación puede pasar a otra página. Es común que una página permanezca activa durante varios turnos de conversación.
- Los flujos son grupos de páginas relacionadas. Cada flujo debe controlar un tema de conversación de alto nivel.
- Los controladores de estado
se usan para controlar las transiciones y las respuestas.
Existen tres tipos de controladores de estado:
- Ruta de intent: Contiene un intent que debe coincidir, respuestas opcionales y una transición de página opcional.
- Ruta de condición: Contiene una condición que se debe cumplir, respuestas opcionales y una transición de página opcional.
- Controlador de eventos: Contiene un nombre de evento que se debe invocar, respuestas opcionales y transición de página opcional.
- El alcance se usa para controlar si se puede llamar a un controlador de estado. La mayoría de los controladores están asociados con una página o un flujo completo. Si la página o el flujo asociados están activos, el controlador está dentro del alcance y se puede llamar. Una ruta de intent de Dialogflow CX dentro del alcance es similar a un intent de Dialogflow ES con un contexto de entrada activo.
Cuando diseñes los flujos y las páginas de tu agente, asegúrate de comprender los consejos de la sección de flujo de la guía de diseño de agentes.
Relleno de formularios
Dialogflow ES usa el completado de ranuras para recopilar los parámetros obligatorios del usuario final:
- Estos son parámetros de intent marcados como obligatorios.
- El intent se sigue coincidiendo hasta que se recopilan todos los parámetros obligatorios.
- Puedes definir un mensaje que le pida al usuario final que proporcione un valor.
Dialogflow CX usa el completado de formularios para recopilar los parámetros obligatorios del usuario final:
- Estos parámetros se asocian con una página y se recopilan mientras la página está activa.
- Usa rutas de condición para que las páginas determinen que se completó el formulario. Por lo general, estas rutas de condición realizan la transición a otra página.
- Puedes definir un mensaje, así como controladores de mensajes de reintento para controlar de forma correcta varios intentos de recopilar un valor.
Transiciones
Dialogflow ES realiza la transición automática de un intent al siguiente cuando la entrada del usuario final coincide con un intent. Esta coincidencia solo puede ocurrir para intents que no tienen contexto de entrada o intents que tienen un contexto de entrada activo.
Dialogflow CX realiza la transición de una página a la siguiente cuando un controlador de estado en el alcance cumple con sus requisitos y proporciona un destino de transición. Con estas transiciones, puedes guiar de forma confiable a los usuarios finales a través de las conversaciones. Existen varias formas de controlar estas transiciones:
- La coincidencia de intents puede activar una ruta de intent.
- Cumplir con una condición puede activar una ruta de condición.
- La invocación de un evento puede activar un controlador de eventos.
- Los controladores de repetición de instrucciones pueden provocar una transición cuando el usuario final no proporciona un valor después de varios intentos.
- Puedes usar destinos de transición simbólicos para los destinos de transición.
Respuestas del agente
Las respuestas del agente de Dialogflow ES se envían al usuario final cuando se detecta una coincidencia con un intent:
- El agente puede seleccionar un mensaje para la respuesta de una lista de respuestas posibles.
- Las respuestas pueden ser específicas de la plataforma, que pueden usar formatos de respuesta enriquecidos.
- Las respuestas pueden ser impulsadas por webhooks.
Las respuestas del agente de Dialogflow CX se envían al usuario final cuando se llama a la entrega. A diferencia de la entrega de Dialogflow ES, que siempre implica un webhook, la entrega de Dialogflow CX puede implicar o no llamar a un webhook, según si el recurso de entrega tiene un webhook configurado. La entrega controla las respuestas estáticas y dinámicas basadas en las respuestas del webhook. Existen varias formas de crear respuestas del agente:
- Se puede proporcionar entrega a cualquier tipo de controlador de estado.
- Se pueden concatenar varias respuestas durante un turno de conversación a través de la cola de respuestas. En algunos casos, esta función puede simplificar el diseño de tu agente.
- Dialogflow CX no admite respuestas integradas específicas de la plataforma. Sin embargo, proporciona varios tipos de respuestas, incluida una carga útil personalizada que se puede usar para respuestas específicas de la plataforma.
Parámetros
Los parámetros de Dialogflow ES tienen las siguientes características:
- Se define solo en intents.
- Se establecen mediante entradas del usuario final, eventos, webhooks y llamadas a la API.
- Se hace referencia a ellos en las respuestas, los mensajes de parámetros, el código de webhook y los
valores de los parámetros:
- El formato de referencia básico es
$parameter-name. - Las referencias admiten la sintaxis de sufijo
.original,.partialy.recent. - Las referencias pueden especificar el contexto activo:
#context-name.parameter-name. - Las referencias pueden especificar parámetros de evento:
#event-name.parameter-name.
- El formato de referencia básico es
Los parámetros de Dialogflow CX tienen las siguientes características:
- Se definen en intents y formularios de páginas.
- Los parámetros de intent y de formulario se propagan a los parámetros de sesión, en los que están disponibles para hacer referencia durante la sesión.
- Se establece mediante la entrada del usuario final, los webhooks, el parámetro de entrega predeterminado y las llamadas a la API.
- Se hace referencia a ellos en las respuestas, las instrucciones de parámetros, los controladores de nuevas instrucciones,
los parámetros predeterminados y el código de webhook:
- El formato de referencia es
$session.params.parameter-idpara los parámetros de sesión y$intent.params.parameter-idpara los parámetros de intent. - Las referencias de parámetros de intents admiten la sintaxis de sufijos
.originaly.resolved. Los parámetros de sesión no admiten esta sintaxis.
- El formato de referencia es
Entidades del sistema
Dialogflow ES admite muchas entidades del sistema.
Dialogflow CX admite muchas de las mismas entidades del sistema, pero hay algunas diferencias. Cuando realices la migración, verifica que las entidades del sistema que usas en Dialogflow ES también sean compatibles con Dialogflow CX para el mismo idioma. De lo contrario, deberías crear entidades personalizadas para estos.
Eventos
Los eventos de Dialogflow ES tienen las siguientes características:
- Se puede invocar desde llamadas a la API o webhooks para que coincida con un intent.
- Puede establecer parámetros.
- Las plataformas de integración invocan una pequeña cantidad de eventos.
Los eventos de Dialogflow CX tienen las siguientes características:
- Se puede invocar desde llamadas a la API o webhooks para llamar a un controlador de eventos.
- No se pueden establecer los parámetros.
- Muchos eventos integrados se pueden usar para controlar la falta de entrada del usuario final, la entrada del usuario final no reconocida, los parámetros invalidados por un webhook y los errores de webhook.
- Las invocaciones se pueden controlar con las mismas reglas de alcance que otros controladores de estado.
Intents integrados
Dialogflow ES admite los siguientes intents integrados:
A continuación, se describe la compatibilidad de Dialogflow CX con los intents integrados:
- Se admiten los intents de bienvenida.
- No se proporcionan intents de resguardo. En su lugar, usa los eventos sin coincidencias en los controladores de eventos.
- Para los ejemplos negativos, usa el intent negativo predeterminado.
- No se proporcionan intents de seguimiento predefinidos. Debes crear estos intents según lo requiera tu agente. Por ejemplo, es probable que debas crear un intent para controlar las respuestas negativas a una pregunta del agente ("no", "no, gracias", "no, no quiero", etcétera). Los intents de Dialogflow CX se pueden reutilizar en todo el agente, por lo que solo debes definirlos una vez. Usar diferentes rutas de intents para estos intents comunes, en diferentes alcances, te brinda un control mucho mejor de la conversación.
Webhooks
Los webhooks de Dialogflow ES tienen las siguientes características:
- Puedes configurar un servicio de webhook para el agente.
- Cada intent se puede marcar como que usa el webhook.
- No hay compatibilidad integrada para controlar los errores de webhook.
- Los webhooks usan las acciones o los nombres de los intents para determinar desde dónde se los llamó en el agente.
- La consola proporciona el editor directo.
Los webhooks de Dialogflow CX tienen las siguientes características:
- Puedes configurar varios servicios de webhook para el agente.
- Cada entrega puede especificar de forma opcional una llamada de webhook.
- Hay compatibilidad integrada para el manejo de errores de webhook.
- Un webhook de entrega de Dialogflow CX contiene una etiqueta. Esta etiqueta es similar a una acción de Dialogflow ES, pero solo se usa cuando se llama a webhooks. El servicio de webhook puede usar estas etiquetas para determinar desde qué parte del agente se lo llamó.
- La consola no tiene un editor de código de webhook integrado. Es común usar Cloud Run Functions, pero hay muchas opciones.
Cuando migres a Dialogflow CX, deberás cambiar el código del webhook, ya que las propiedades de solicitud y respuesta son diferentes.
Integraciones
Las integraciones de Dialogflow ES y las integraciones de Dialogflow CX admiten diferentes plataformas. En el caso de las plataformas compatibles con ambos tipos de agentes, puede haber diferencias en la configuración.
Si la integración de Dialogflow ES que usabas no es compatible con Dialogflow CX, es posible que debas cambiar de plataforma o implementar la integración por tu cuenta.
Más funciones exclusivas de Dialogflow CX
Hay muchas otras funciones que solo proporciona Dialogflow CX. Te recomendamos que uses estas funciones durante la migración. Por ejemplo:
- CLN avanzada
- Configuración de voz avanzada (sensibilidad cuando se deja de escuchar una voz, tiempo de espera sin voz, etcétera)
- Historial de cambios
- Lógica condicional
- Entrada de DTMF para integraciones de telefonía
- Webhooks específicos del entorno
- Experimentos
- Grupos de rutas
- Datos de agentes de búsqueda
- Configuración de seguridad (redacción y retención de datos)
- Funciones del sistema para respuestas y condiciones avanzadas
- Casos de prueba
- Validación de los datos del agente
Prácticas recomendadas
Antes de migrar, familiarízate con las prácticas recomendadas para el diseño de agentes de Dialogflow CX. Muchas de estas prácticas recomendadas de Dialogflow CX son similares a las de Dialogflow ES, pero algunas son exclusivas de Dialogflow CX.
Acerca de la herramienta de migración
La herramienta de migración copia la mayor parte de los datos de Dialogflow ES en tu agente de Dialogflow CX y escribe en un archivo TODO con una lista de elementos que se deben migrar de forma manual. La herramienta solo copia los tipos de entidades personalizadas y las frases de entrenamiento de intents. Te recomendamos personalizar esta herramienta según tus necesidades específicas.
Código de la herramienta de migración
Este es el código de la herramienta. Deberías revisar el código de esta herramienta para comprender lo que hace. Es posible que desees cambiar este código para controlar situaciones específicas en tu agente. En los pasos que se indican a continuación, ejecutarás esta herramienta.
// 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() }
Migración de tipos de entidad con la herramienta
Los tipos de entidades de Dialogflow ES y los tipos de entidades de Dialogflow CX son muy similares, por lo que son el tipo de datos más fácil de migrar. La herramienta simplemente copia los tipos de entidades tal como están.
Migración de intents de herramientas
Los intents de Dialogflow ES y los intents de Dialogflow CX son muy diferentes.
Los intents de Dialogflow ES se usan como los componentes básicos del agente y contienen frases de entrenamiento, respuestas, contexto para el control de conversaciones, parámetros de configuración de webhooks, eventos, acciones y parámetros de llenado de ranuras.
Dialogflow CX movió la mayoría de estos datos a otros recursos. Los intents de Dialogflow CX solo tienen frases de entrenamiento y parámetros, lo que hace que los intents se puedan reutilizar en todo el agente. La herramienta solo copia estos dos tipos de datos de intents en tus intents de Dialogflow CX.
Limitaciones de la herramienta de migración
La herramienta de migración no admite lo siguiente:
- Agentes combinados: La herramienta no puede leer de varios subagentes, pero puedes llamarla varias veces para cada subagente.
- Agentes multilingües: Debes modificar la herramienta para crear frases de entrenamiento y entradas de entidades multilingües.
- Verificación de entidades del sistema para idiomas que no sean inglés: La herramienta crea elementos TODO cuando encuentra entidades del sistema que no son compatibles con Dialogflow CX, con la suposición de que el inglés es el idioma predeterminado y que usa una región de EE.UU. La compatibilidad con las entidades del sistema varía según el idioma y la región. Para otros idiomas y regiones, debes modificar la herramienta para que realice esta verificación.
Pasos esenciales para la migración
En las siguientes subsecciones, se describen los pasos de migración que se deben seguir. No es necesario que sigas estos pasos manuales en orden, e incluso es posible que debas realizarlos de forma simultánea o en un orden diferente. Lee los pasos y comienza a planificar los cambios antes de realizarlos.
Después de ejecutar la herramienta de migración, puedes volver a compilar tu agente de Dialogflow CX. Aún tendrás que realizar una gran cantidad de trabajo de migración, pero la mayor parte de los datos ingresados de forma manual estará presente en tu agente de Dialogflow CX y en el archivo TODO.
Crea tu agente de Dialogflow CX
Si aún no lo hiciste, crea tu agente de Dialogflow CX. Asegúrate de usar el mismo idioma predeterminado que tu agente de Dialogflow ES.
Ejecuta la herramienta de migración
Sigue estos pasos para ejecutar la herramienta:
- Si aún no lo hiciste, instala Go en tu máquina.
- Crea un directorio para el código de la herramienta llamado
migrate. - Copia el código de la herramienta anterior
en un archivo de este directorio llamado
main.go. - Modifica el código si es necesario para tu caso.
Crea un módulo de Go en este directorio. Por ejemplo:
go mod init migrateInstala las bibliotecas cliente de Go de Dialogflow ES V2 y Dialogflow CX V3:
go get cloud.google.com/go/dialogflow/apiv2 go get cloud.google.com/go/dialogflow/cx/apiv3Asegúrate de haber configurado la autenticación de la biblioteca cliente.
Ejecuta la herramienta y guarda el resultado en un archivo:
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
Solución de problemas de la herramienta de migración
Si se producen errores cuando ejecutas la herramienta, verifica lo siguiente:
| Error | Solución |
|---|---|
| Error de RPC que indica que una parte de la frase de entrenamiento menciona un parámetro no definido para el intent. | Esto puede suceder si antes usaste la API de Dialogflow ES para crear parámetros de intents de una manera que no era coherente con las frases de entrenamiento. Para solucionar este problema, cambia el nombre del parámetro de Dialogflow ES desde la consola, verifica que tus frases de entrenamiento usen el parámetro correctamente y, luego, haz clic en Guardar. Esto también puede suceder si tus frases de entrenamiento hacen referencia a parámetros inexistentes. |
Después de corregir los errores, deberás borrar los intents y las entidades del agente de Dialogflow CX antes de volver a ejecutar la herramienta de migración.
Mueve los datos de intents de Dialogflow ES a Dialogflow CX
La herramienta migra las frases de entrenamiento y los parámetros de los intents a los intents de Dialogflow CX, pero hay muchos otros campos de intents de Dialogflow ES que se deben migrar de forma manual.
Un intent de Dialogflow ES puede necesitar una página de Dialogflow CX correspondiente, un intent de Dialogflow CX correspondiente o ambos.
Si se usa una coincidencia de intent de Dialogflow ES para realizar la transición de la conversación de un nodo de conversación en particular a otro, debes tener dos páginas en tu agente relacionadas con este intent:
- La página original que contiene la ruta de intent, que pasará a la página siguiente: La ruta de intent en la página original puede tener mensajes de entrega de Dialogflow CX similares a las respuestas de intents de Dialogflow ES. Es posible que tengas muchas rutas de intents en esta página. Mientras la página original está activa, estas rutas de intents pueden hacer que la conversación tome muchos caminos posibles. Muchos intents de Dialogflow ES compartirán la misma página original de Dialogflow CX correspondiente.
- La página siguiente, que es el destino de transición para la ruta de intents en la página original: La entrega de entrada de Dialogflow CX para la página siguiente puede tener mensajes de entrega de Dialogflow CX similares a las respuestas de intents de Dialogflow ES.
Si un intent de Dialogflow ES contiene parámetros obligatorios, debes crear una página de Dialogflow CX correspondiente con los mismos parámetros en un formulario.
Es común que un intent de Dialogflow CX y una página de Dialogflow CX compartan la misma lista de parámetros, lo que significaría que un solo intent de Dialogflow ES tiene una página de Dialogflow CX correspondiente y un intent de Dialogflow CX correspondiente. Cuando se encuentra una coincidencia con un intent de Dialogflow CX con parámetros en una ruta de intent, la conversación suele pasar a una página con los mismos parámetros. Los parámetros extraídos de la coincidencia de intents se propagan a los parámetros de sesión, que están disponibles para completar de forma parcial o total los parámetros del formulario de la página.
Los intents de resguardo y los intents de seguimiento predefinidos no existen en Dialogflow CX. Consulta intents integrados.
En la siguiente tabla, se describe cómo asignar datos de intents específicos de Dialogflow ES a recursos de Dialogflow CX:
| Datos de intents de Dialogflow ES | Datos de Dialogflow CX correspondientes | Acción obligatoria |
|---|---|---|
| Frases de entrenamiento | Frases de entrenamiento de intents | Se migró con la herramienta. La herramienta verifica la compatibilidad con entidades del sistema y crea elementos TODO para las entidades del sistema no compatibles. |
| Respuestas del agente | Mensajes de respuesta de entrega | Consulta las respuestas del agente. |
| Contexto para el control de conversaciones | Ninguno | Consulta Control de la estructura y la ruta de conversación. |
| Configuración de webhook | Configuración del webhook de entrega | Consulta Webhooks. |
| Eventos | Controladores de eventos a nivel del flujo o de la página | Consulta los eventos. |
| Acciones | Etiquetas de webhook de entrega | Consulta Webhooks. |
| Parámetros | Parámetros de intents o parámetros de formularios de páginas | Se migraron a parámetros de intents por herramienta. Si los parámetros son obligatorios, la herramienta crea elementos TODO para, posiblemente, migrar a una página. Consulta los parámetros. |
| Mensajes de parámetros | Mensajes de parámetros de formularios de páginas | Consulta Cómo completar formularios. |
Crear flujos
Crea un flujo para cada tema de conversación de alto nivel. Los temas de cada flujo deben ser distintos, de modo que la conversación no salte con frecuencia entre los flujos.
Si usabas un agente combinado, cada agente secundario debería convertirse en uno o más flujos.
Comienza con rutas de conversación básicas
Se recomienda probar el agente con el simulador mientras se realizan iteraciones en los cambios. Por lo tanto, inicialmente debes enfocarte en las rutas de conversación básicas al principio de la conversación y realizar pruebas a medida que haces cambios. Una vez que funcionen, pasa a rutas de conversación más detalladas.
Controladores de estado a nivel de flujo frente a los de nivel de página
Cuando crees controladores de estado, considera si deben aplicarse a nivel del flujo o de la página. Un controlador a nivel del flujo está dentro del alcance siempre que el flujo (y, por lo tanto, cualquier página dentro del flujo) esté activo. Un controlador a nivel de página solo está dentro del alcance cuando la página en particular está activa. Los controladores a nivel del flujo son similares a los intents de Dialogflow ES sin contexto de entrada. Los controladores a nivel de página son similares a los intents de Dialogflow ES con contexto de entrada.
Código de webhook
Las propiedades de solicitud y respuesta del webhook son diferentes para Dialogflow CX. Consulta la sección de webhooks.
Conectores de conocimiento
Dialogflow CX aún no admite conectores de conocimiento. Deberás implementarlos como intents normales o esperar hasta que Dialogflow CX admita conectores de conocimiento.
Configuración de agentes
Revisa la configuración de tu agente de Dialogflow ES y ajusta la configuración de tu agente de Dialogflow CX según sea necesario.
Usa el archivo TODO
La herramienta de migración genera un archivo CSV. Los elementos de esta lista se enfocan en datos específicos que podrían requerir atención. Importa este archivo a una hoja de cálculo. Resuelve cada elemento de la hoja de cálculo y usa una columna para marcar la finalización.
Migración del uso de la API
Si tu sistema usa la API de Dialogflow ES para las llamadas de tiempo de ejecución o de diseño, deberás actualizar este código para usar la API de Dialogflow CX. Si solo usas las llamadas de detección de intents en el entorno de ejecución, esta actualización debería ser bastante sencilla.
Integraciones
Si tu agente usa integraciones, consulta la sección de integraciones y realiza los cambios necesarios.
Pasos recomendados para la migración
En las siguientes subsecciones, se describen los pasos de migración recomendados.
Validación
Usa la validación de agentes para verificar que tu agente siga las prácticas recomendadas.
Pruebas
Mientras realizas los pasos de migración manual anteriores, debes probar tu agente con el simulador. Una vez que tu agente parezca estar funcionando, deberías comparar las conversaciones entre tus agentes de Dialogflow ES y Dialogflow CX, y verificar que el comportamiento sea similar o mejor.
Mientras pruebas estas conversaciones con el simulador, debes crear casos de prueba para evitar regresiones futuras.
Entornos
Revisa tus entornos de Dialogflow ES y actualiza tus entornos de Dialogflow CX según sea necesario.