Crea bots de voz para Android con Dialogflow Essentials & Oscilación

1. Antes de comenzar

En este codelab, aprenderás a integrar un bot de voz y texto de Dialogflow Essentials (ES) en una app creada con Flutter. Dialogflow ES es un paquete de desarrollo para crear IU conversacionales. Por ejemplo, chatbots, bots de voz y puertas de enlace telefónicas. Todos pueden compilarlo con la misma herramienta y hasta pueden admitir varios canales en más de 20 idiomas diferentes. Dialogflow se integra con muchas plataformas de conversación populares, como Asistente de Google, Slack y Facebook Messenger. Si deseas compilar un agente para una de estas plataformas, debes usar una de las muchas opciones de integración. Sin embargo, para crear un chatbot para dispositivos móviles, deberás crear una integración personalizada. Para crear intents, especificarás frases de entrenamiento para entrenar un modelo de aprendizaje automático subyacente.

Este lab se ordenó para reflejar una experiencia común de desarrollador de la nube:

  1. Configuración del entorno
  • Dialogflow: Crea un agente nuevo de Dialogflow ES
  • Dialogflow: Cómo configurar Dialogflow
  • Google Cloud: Crea una cuenta de servicio
  1. Flutter: cómo crear una aplicación de chat
  • Crea un proyecto de Flutter
  • Establece la configuración y los permisos
  • Agrega las dependencias
  • Se está vinculando la cuenta de servicio.
  • Ejecuta la aplicación en un dispositivo virtual o físico
  1. Flutter: creación de la interfaz de chat compatible con Speech-to-Text
  • Crea la interfaz de chat
  • Vincula la interfaz de chat
  • Integra el paquete de gRPC de Dialogflow en la app
  1. Dialogflow: Modelar el agente de Dialogflow
  • Configura los mensajes de bienvenida y intents de resguardo
  • Hacer uso de una base de conocimiento de preguntas frecuentes

Requisitos

  • Experiencia básica de Dart/Flutter
  • Experiencia básica en Google Cloud Platform
  • Experiencia básica con Dialogflow ES

Qué compilarás

En este codelab, te mostraremos cómo compilar un bot de preguntas frecuentes para dispositivos móviles, que puede responder las preguntas más comunes sobre la herramienta Dialogflow. Los usuarios finales pueden interactuar con la interfaz de texto o transmitir una voz a través del micrófono integrado de un dispositivo móvil para obtener respuestas.

Qué aprenderás

  • Cómo crear un chatbot con Dialogflow Essentials
  • Cómo integrar Dialogflow en una app de Flutter con el paquete de gRPC de Dialogflow
  • Cómo detectar intents de texto con Dialogflow
  • Cómo transmitir una voz a Dialogflow por medio del micrófono
  • Cómo usar el conector de la base de conocimiento para importar preguntas frecuentes públicas
  • Probar el chatbot a través de la interfaz de texto y voz en un dispositivo virtual o físico

Requisitos

  • Para crear un agente de Dialogflow, necesitarás una dirección de Gmail o Google Identity.
  • Necesitarás acceso a Google Cloud Platform para descargar una cuenta de servicio
  • Entorno de desarrollo de Flutter

Configura tu entorno de desarrollo de Flutter

  1. Selecciona el sistema operativo en el que instalas Flutter.
  1. Puedes compilar apps con Flutter usando cualquier editor de texto combinado con nuestras herramientas de línea de comandos. Sin embargo, para este taller se usará Android Studio. Los complementos de Flutter y Dart para Android Studio te proporcionan funciones de finalización de código, resaltado de sintaxis, ayuda con la edición de widgets, ejecución y la depuración y más. Sigue los pasos que se indican en https://flutter.dev/docs/get-started/editor.

2. Configuración del entorno

Dialogflow: Crea un agente nuevo de Dialogflow ES

  1. Abre la .
  2. En la barra izquierda, debajo del logotipo, selecciona "Create New Agent". en el menú desplegable. Ten en cuenta que no hagas clic en el menú desplegable que dice “Global”, ya que necesitaremos una instancia de Dialogflow que sea global para usar la base de conocimiento de Preguntas frecuentes.
  3. Especifica un nombre de agente yourname-dialogflow (usa tu propio nombre)
  4. Como idioma predeterminado, selecciona English - en.
  5. Como zona horaria predeterminada, elige la más cercana.
  6. No selecciones Mega Agent. (Con esta función, puedes crear un agente general, que puede organizar entre agentes "sub". No lo necesitamos ahora).
  7. Haz clic en Crear.

Pantalla para crear un proyecto nuevo

Configura Dialogflow

  1. Haz clic en el ícono de ajustes en el menú de la izquierda, junto al nombre del proyecto.

Menú desplegable para crear un proyecto nuevo

  1. Ingresa la siguiente descripción del agente: Dialogflow FAQs Chatbot.
  2. Gira el interruptor para habilitar las funciones beta.

Dialogflow Essentials V2Beta1

  1. Haz clic en la pestaña Voz y asegúrate de que la casilla Adaptación de voz automática esté activa.
  2. De forma opcional, también puedes activar el primer interruptor para mejorar el modelo de voz, pero solo está disponible cuando actualizas la prueba de Dialogflow.
  3. Haga clic en Guardar.

Google Cloud: Obtén una cuenta de servicio

Después de crear un agente en Dialogflow, se debe crear un proyecto de Google Cloud en la consola de Google Cloud.

  1. Abre la consola de Google Cloud: .
  2. Asegúrate de haber accedido con la misma Cuenta de Google que en Dialogflow y selecciona el proyecto yourname-dialogflow en la barra azul superior.
  3. Luego, busca Dialogflow API en la barra de herramientas superior y haz clic en el resultado de la API de Dialogflow en el menú desplegable.

Habilitar la API de Dialogflow

  1. Haz clic en el botón azul Administrar y, luego, en Credenciales en la barra de menú de la izquierda. (Cuando Dialogflow aún no esté habilitado, primero presiona Habilitar).

Credenciales de la consola de GCP

  1. Haz clic en Crear credenciales (en la parte superior de la pantalla) y elige Cuenta de servicio.

Crear credenciales

  1. Especifica un nombre de cuenta de servicio (flutter_dialogflow, ID y descripción) y, luego, haz clic en Crear.

Crea una cuenta de servicio

  1. En el paso 2, deberás seleccionar el rol Dialogflow API Admin, hacer clic en Continuar y Listo.
  2. Haz clic en la cuenta de servicio flutter_dialogflow, luego en la pestaña Claves y selecciona Agregar clave > Crear clave nueva

Crear clave

  1. Crea una clave JSON. Cámbiale el nombre a credentials.json y almacénalo en algún lugar de una ubicación segura del disco duro. Lo usaremos más adelante.

Clave JSON

Perfecto. Todas las herramientas que necesitamos están configuradas correctamente. Ahora podemos comenzar con la integración de Dialogflow en nuestra app.

3. Flutter: Cómo compilar la aplicación de chat

Crea la app Boilerplate

  1. Abre Android Studio y selecciona Start a new Flutter project.
  2. Selecciona Flutter Application como el tipo de proyecto. Luego, haz clic en Siguiente.
  3. Verifica que la ruta del SDK de Flutter especifique la ubicación del SDK (selecciona Instalar el SDK... si el campo de texto está en blanco).
  4. Ingresa un nombre de proyecto (por ejemplo, flutter_dialogflow_agent). Luego, haz clic en Siguiente.
  5. Modifica el nombre del paquete y haz clic en Finish.

Crea una nueva aplicación de Flutter

Se creará una aplicación de ejemplo con componentes de Material.

Espera a que Android Studio instale el SDK y cree el proyecto.

Configuración y Permisos

  1. La biblioteca de la grabadora de audio sound_stream que usaremos requiere un minSdk de al menos 21. Por lo tanto, cambiemos esto en android/app/build.gradle, en el bloque defaultConfig. (Ten en cuenta que hay 2 archivos build.gradle en la carpeta de Android, pero el de la carpeta de la app es el correcto).
defaultConfig {
   applicationId "com.myname.flutter_dialogflow_agent"
   minSdkVersion 21
   targetSdkVersion 30
   versionCode flutterVersionCode.toInteger()
   versionName flutterVersionName
}
  1. Para otorgar permisos al micrófono y permitir que la aplicación se comunique con el agente de Dialogflow que se ejecuta en la nube, tendremos que agregar los permisos de INTERNET y RECORD_AUDIO al archivo app/src/main/AndroidManifest.xml. Hay varios archivos AndroidManifest.xml en tu proyecto de Flutter, pero necesitarás uno que esté en la carpeta principal. Puedes agregar las líneas directamente dentro de las etiquetas del manifiesto.
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />

Agrega las dependencias

Usaremos los paquetes sound_stream, rxdart y dialogflow_grpc.

  1. Cómo agregar la dependencia sound_stream
$ flutter pub add sound_stream
Resolving dependencies...
  async 2.8.1 (2.8.2 available)
  characters 1.1.0 (1.2.0 available)
  matcher 0.12.10 (0.12.11 available)
+ sound_stream 0.3.0
  test_api 0.4.2 (0.4.5 available)
  vector_math 2.1.0 (2.1.1 available)
Downloading sound_stream 0.3.0...
Changed 1 dependency!
  1. Cómo agregar la dependencia dialogflow_grpc
flutter pub add dialogflow_grpc
Resolving dependencies...
+ archive 3.1.5
  async 2.8.1 (2.8.2 available)
  characters 1.1.0 (1.2.0 available)
+ crypto 3.0.1
+ dialogflow_grpc 0.2.9
+ fixnum 1.0.0
+ googleapis_auth 1.1.0
+ grpc 3.0.2
+ http 0.13.4
+ http2 2.0.0
+ http_parser 4.0.0
  matcher 0.12.10 (0.12.11 available)
+ protobuf 2.0.0
  test_api 0.4.2 (0.4.5 available)
+ uuid 3.0.4
  vector_math 2.1.0 (2.1.1 available)
Downloading dialogflow_grpc 0.2.9...
Downloading grpc 3.0.2...
Downloading http 0.13.4...
Downloading archive 3.1.5...
Changed 11 dependencies!
  1. Cómo agregar la dependencia rxdart
$ flutter pub add rxdart
Resolving dependencies...
  async 2.8.1 (2.8.2 available)
  characters 1.1.0 (1.2.0 available)
  matcher 0.12.10 (0.12.11 available)
+ rxdart 0.27.2
  test_api 0.4.2 (0.4.5 available)
  vector_math 2.1.0 (2.1.1 available)
Downloading rxdart 0.27.2...
Changed 1 dependency!

Carga la cuenta de servicio y la información del proyecto de Google Cloud

  1. En tu proyecto, crea un directorio y asígnale el nombre assets.
  2. Mueve el archivo credentials.json que descargaste de la consola de Google Cloud a la carpeta assets.
  3. Abre pubspec.yaml y agrega la cuenta de servicio al bloque de Flutter.
flutter:
  uses-material-design: true
  assets:
    - assets/credentials.json

Ejecuta la aplicación en un dispositivo físico

Si tienes un dispositivo Android, puedes conectar tu teléfono mediante un cable USB y depurar en el dispositivo. Sigue estos pasos para realizar la configuración desde la pantalla Opciones para desarrolladores de tu dispositivo Android.

Ejecuta la aplicación en un dispositivo virtual

Si deseas ejecutar la aplicación en un dispositivo virtual, sigue estos pasos:

  1. Haz clic en Herramientas > Administrador de AVD (O selecciona el Administrador de AVD en la barra de herramientas superior; en la siguiente imagen, aparece resaltado en rosa).

Barra de herramientas superior de Android Studio

  1. Crearemos un dispositivo virtual de Android de destino, de modo que podamos probar nuestra aplicación sin un dispositivo físico. Para obtener más información, consulta Cómo administrar AVD. Una vez que hayas seleccionado un nuevo dispositivo virtual, puedes hacer doble clic en él para iniciarlo.

Cómo administrar AVD

Dispositivo virtual

  1. En la barra de herramientas principal de Android Studio, selecciona un dispositivo Android como destino en el menú desplegable y asegúrate de que esté seleccionada la opción main.dart. Luego, presiona el botón Run (triángulo verde).

En la parte inferior del IDE, verás los registros en la consola. Notarás que instala Android y tu app de inicio de Flutter. Esto tardará un minuto. Una vez que el dispositivo virtual esté listo, los cambios serán muy rápidos. Cuando termines, se abrirá la app de inicio de Flutter.

App de plantilla

  1. Vamos a habilitar el micrófono para nuestra aplicación de chatbot. Haz clic en el botón options del dispositivo virtual para abrir las opciones. En la pestaña Micrófono, habilita los 3 interruptores.

Opciones de AVD

  1. Probemos la recarga en caliente para demostrar la rapidez con la que se pueden realizar cambios.

En lib/main.dart, cambia el título de MyHomePage en la clase MyApp a: Flutter Dialogflow Agent. Y cambia primarySwatch a Colors.orange.

Primer código

Guarda el archivo o haz clic en el ícono de rayo en la barra de herramientas de Android Studio. Deberías ver el cambio directamente en el dispositivo virtual.

4. Flutter: Cómo compilar la interfaz de chat compatible con STT

Crea la interfaz de chat

  1. Crea un nuevo archivo de widget de Flutter en la carpeta lib. (haz clic con el botón derecho en la carpeta lib, New > Flutter Widget > Stateful widget), llama a este archivo: chat.dart

Pega el siguiente código en este archivo. Este archivo de dart crea la interfaz de chat. Dialogflow aún no funcionará. Es solo el diseño de todos los componentes y la integración del componente del micrófono para permitir transmisiones. Se señalarán los comentarios en el archivo, donde más adelante integraremos Dialogflow.

// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rxdart/rxdart.dart';
import 'package:sound_stream/sound_stream.dart';

// TODO import Dialogflow


class Chat extends StatefulWidget {
  Chat({Key key}) : super(key: key);

  @override
  _ChatState createState() => _ChatState();
}

class _ChatState extends State<Chat> {
  final List<ChatMessage> _messages = <ChatMessage>[];
  final TextEditingController _textController = TextEditingController();

  bool _isRecording = false;

  RecorderStream _recorder = RecorderStream();
  StreamSubscription _recorderStatus;
  StreamSubscription<List<int>> _audioStreamSubscription;
  BehaviorSubject<List<int>> _audioStream;

  // TODO DialogflowGrpc class instance

  @override
  void initState() {
    super.initState();
    initPlugin();
  }

  @override
  void dispose() {
    _recorderStatus?.cancel();
    _audioStreamSubscription?.cancel();
    super.dispose();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlugin() async {
    _recorderStatus = _recorder.status.listen((status) {
      if (mounted)
        setState(() {
          _isRecording = status == SoundStreamStatus.Playing;
        });
    });

    await Future.wait([
      _recorder.initialize()
    ]);



    // TODO Get a Service account

  }

  void stopStream() async {
    await _recorder.stop();
    await _audioStreamSubscription?.cancel();
    await _audioStream?.close();
  }

  void handleSubmitted(text) async {
    print(text);
    _textController.clear();

    //TODO Dialogflow Code

  }

  void handleStream() async {
    _recorder.start();

    _audioStream = BehaviorSubject<List<int>>();
    _audioStreamSubscription = _recorder.audioStream.listen((data) {
      print(data);
      _audioStream.add(data);
    });


    // TODO Create SpeechContexts
    // Create an audio InputConfig

    // TODO Make the streamingDetectIntent call, with the InputConfig and the audioStream
    // TODO Get the transcript and detectedIntent and show on screen

  }

  // The chat interface
  //
  //------------------------------------------------------------------------------------
  @override
  Widget build(BuildContext context) {
    return Column(children: <Widget>[
      Flexible(
          child: ListView.builder(
            padding: EdgeInsets.all(8.0),
            reverse: true,
            itemBuilder: (_, int index) => _messages[index],
            itemCount: _messages.length,
          )),
      Divider(height: 1.0),
      Container(
          decoration: BoxDecoration(color: Theme.of(context).cardColor),
          child: IconTheme(
            data: IconThemeData(color: Theme.of(context).accentColor),
            child: Container(
              margin: const EdgeInsets.symmetric(horizontal: 8.0),
              child: Row(
                children: <Widget>[
                  Flexible(
                    child: TextField(
                      controller: _textController,
                      onSubmitted: handleSubmitted,
                      decoration: InputDecoration.collapsed(hintText: "Send a message"),
                    ),
                  ),
                  Container(
                    margin: EdgeInsets.symmetric(horizontal: 4.0),
                    child: IconButton(
                      icon: Icon(Icons.send),
                      onPressed: () => handleSubmitted(_textController.text),
                    ),
                  ),
                  IconButton(
                    iconSize: 30.0,
                    icon: Icon(_isRecording ? Icons.mic_off : Icons.mic),
                    onPressed: _isRecording ? stopStream : handleStream,
                  ),
                ],
              ),
            ),
          )
      ),
    ]);
  }
}


//------------------------------------------------------------------------------------
// The chat message balloon
//
//------------------------------------------------------------------------------------
class ChatMessage extends StatelessWidget {
  ChatMessage({this.text, this.name, this.type});

  final String text;
  final String name;
  final bool type;

  List<Widget> otherMessage(context) {
    return <Widget>[
      new Container(
        margin: const EdgeInsets.only(right: 16.0),
        child: CircleAvatar(child: new Text('B')),
      ),
      new Expanded(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(this.name,
                style: TextStyle(fontWeight: FontWeight.bold)),
            Container(
              margin: const EdgeInsets.only(top: 5.0),
              child: Text(text),
            ),
          ],
        ),
      ),
    ];
  }

  List<Widget> myMessage(context) {
    return <Widget>[
      Expanded(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: <Widget>[
            Text(this.name, style: Theme.of(context).textTheme.subtitle1),
            Container(
              margin: const EdgeInsets.only(top: 5.0),
              child: Text(text),
            ),
          ],
        ),
      ),
      Container(
        margin: const EdgeInsets.only(left: 16.0),
        child: CircleAvatar(
            child: Text(
              this.name[0],
              style: TextStyle(fontWeight: FontWeight.bold),
            )),
      ),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.symmetric(vertical: 10.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: this.type ? myMessage(context) : otherMessage(context),
      ),
    );
  }
}

Busca la compilación de widgets en el archivo chat.dart. Esto compila la interfaz del chatbot, que contiene lo siguiente:

  • ListView, que contiene todos los globos de chat del usuario y el chatbot. Usa la clase ChatMessage, que crea mensajes de chat con un avatar y texto.
  • TextField para ingresar consultas de texto
  • IconButton con el ícono de enviar, para enviar consultas de texto a Dialogflow
  • IconButton con un micrófono para enviar transmisiones de audio a Dialogflow, que cambia el estado una vez que se presiona

Vincula la interfaz de chat

  1. Abre main.dart y cambia Widget build, de modo que solo se cree una instancia de la interfaz Chat(). Se pueden quitar todos los demás códigos de demostración.
import 'package:flutter/material.dart';
import 'chat.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.orange,
      ),
      home: MyHomePage(title: 'Flutter Dialogflow Agent'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Chat())
    );
  }
}
  1. Ejecuta la aplicación. (Si la app se inició anteriormente. Detén el dispositivo virtual y vuelve a ejecutar main.dart). Cuando ejecutas tu app con la interfaz de chat por primera vez Aparecerá una ventana emergente para confirmar si deseas habilitar el micrófono. Haz clic en Mientras la app está en uso.

Permisos

  1. Juega con el área de texto y los botones. Cuando escribas una consulta de texto y presiones Intro o presiones el botón de envío, verás la consulta de texto registrada en la pestaña Run de Android Studio. Cuando presiones el botón del micrófono y lo detengas, verás la transmisión de audio registrada en la pestaña Run.

Registro de reproducción de audio

Genial, ya estamos listos para integrar la aplicación en Dialogflow.

Cómo integrar tu app de Flutter con Dialogflow_gRPC

  1. Abre chat.dart y agrega las siguientes importaciones:
import 'package:dialogflow_grpc/dialogflow_grpc.dart';
import 'package:dialogflow_grpc/generated/google/cloud/dialogflow/v2beta1/session.pb.dart';
  1. En la parte superior del archivo, justo debajo de // TODO DialogflowGrpcV2Beta1 class instance, agrega la siguiente línea para que contenga la instancia de clase de Dialogflow:
DialogflowGrpcV2Beta1 dialogflow;
  1. Busca el método initPlugin() y agrega el siguiente código, justo debajo del comentario TODO:
    // Get a Service account
    final serviceAccount = ServiceAccount.fromString(
        '${(await rootBundle.loadString('assets/credentials.json'))}');
    // Create a DialogflowGrpc Instance
    dialogflow = DialogflowGrpcV2Beta1.viaServiceAccount(serviceAccount);

Esto creará una instancia de Dialogflow autorizada para tu proyecto de Google Cloud con la cuenta de servicio. Asegúrate de tener el archivo credentials.json en la carpeta assets.

De nuevo, a los fines de la demostración sobre cómo trabajar con gRPC de Dialogflow, esto está bien, pero para las apps de producción, no se recomienda almacenar el archivo credentials.json en la carpeta de recursos, ya que esto no se considera seguro.

Realiza una llamada a detectIntent

  1. Ahora, busca el método handleSubmitted(). Aquí es donde entra en juego la magia. Justo debajo del comentario TODO, agrega el siguiente código.Este código agregará el mensaje escrito del usuario a ListView:
ChatMessage message = ChatMessage(
 text: text,
 name: "You",
 type: true,
);

setState(() {
 _messages.insert(0, message);
});
  1. Ahora, justo debajo del código anterior, haremos la llamada a detectIntent, pasaremos el texto de la entrada y un languageCode. - El resultado (en data.queryResult.fulfillment) se imprimirá en ListView:
DetectIntentResponse data = await dialogflow.detectIntent(text, 'en-US');
String fulfillmentText = data.queryResult.fulfillmentText;
if(fulfillmentText.isNotEmpty) {
  ChatMessage botMessage = ChatMessage(
    text: fulfillmentText,
    name: "Bot",
    type: false,
  );

  setState(() {
    _messages.insert(0, botMessage);
  });
}
  1. Inicia el dispositivo virtual y prueba la llamada de detección de intent. Tipo: hi. Debería recibir el mensaje de bienvenida predeterminado. Cuando escribas otra cosa, se te mostrará el resguardo predeterminado.

Realiza una llamada streamingDetectIntent

  1. Ahora, busca el método handleStream(). Aquí es donde entra la magia de la transmisión de audio. Primero, justo debajo del primer TODO, crea un audio InputConfigV2beta1 con un sesgoList para personalizar el modelo de voz. Dado que usaremos un teléfono (dispositivo virtual), el valor de sampleHertz será de 16,000 y la codificación será de Linear 16. No depende del hardware de la máquina o del micrófono que utilices. Para mi micrófono interno de MacBook, el 16000 era bueno. (consulta la información del paquete https://pub.dev/packages/sound_stream).
var biasList = SpeechContextV2Beta1(
    phrases: [
      'Dialogflow CX',
      'Dialogflow Essentials',
      'Action Builder',
      'HIPAA'
    ],
    boost: 20.0
);

    // See: https://cloud.google.com/dialogflow/es/docs/reference/rpc/google.cloud.dialogflow.v2#google.cloud.dialogflow.v2.InputAudioConfig
var config = InputConfigV2beta1(
    encoding: 'AUDIO_ENCODING_LINEAR_16',
    languageCode: 'en-US',
    sampleRateHertz: 16000,
    singleUtterance: false,
    speechContexts: [biasList]
);
  1. A continuación, llamaremos al método streamingDetectIntent en el objeto dialogflow, que contiene nuestra sesión de Dialogflow:
final responseStream = dialogflow.streamingDetectIntent(config, _audioStream);
  1. Con responseStream, finalmente podemos escuchar la transcripción entrante, la consulta detectada del usuario y la respuesta de intent coincidente detectada. Imprimiremos esto en un ChatMessage en la pantalla:
// Get the transcript and detectedIntent and show on screen
responseStream.listen((data) {
  //print('----');
  setState(() {
    //print(data);
    String transcript = data.recognitionResult.transcript;
    String queryText = data.queryResult.queryText;
    String fulfillmentText = data.queryResult.fulfillmentText;

    if(fulfillmentText.isNotEmpty) {

      ChatMessage message = new ChatMessage(
        text: queryText,
        name: "You",
        type: true,
      );

      ChatMessage botMessage = new ChatMessage(
        text: fulfillmentText,
        name: "Bot",
        type: false,
      );

      _messages.insert(0, message);
      _textController.clear();
      _messages.insert(0, botMessage);

    }
    if(transcript.isNotEmpty) {
      _textController.text = transcript;
    }

  });
},onError: (e){
  //print(e);
},onDone: () {
  //print('done');
});

Eso es todo. Inicia la aplicación y pruébala en el dispositivo virtual, presiona el botón del micrófono y Di: "Hola".

Esta acción activará el intent de bienvenida predeterminado de Dialogflow. Los resultados se imprimirán en la pantalla. Ahora que Flutter funciona muy bien con la integración de Dialogflow, podemos comenzar a trabajar en nuestra conversación con el chatbot.

5. Dialogflow: Modela el agente de Dialogflow

Dialogflow Essentials es un paquete de desarrollo para crear IU conversacionales. Por ejemplo, chatbots, bots de voz y puertas de enlace telefónicas. Todos pueden compilarlo con la misma herramienta y hasta pueden admitir varios canales en más de 20 idiomas diferentes. Los diseñadores de UX de Dialogflow (agentes modeladores y lingüistas) o desarrolladores crean intents mediante la especificación de frases de entrenamiento para entrenar un modelo de aprendizaje automático subyacente.

Un intent categoriza la intención del usuario. Puedes definir varios intents para cada agente de Dialogflow ES; estos, en combinación, pueden manejar una conversación completa. Cada intent puede contener parámetros y respuestas.

La búsqueda de coincidencias con un intent también se conoce como clasificación o coincidencia de intents. Este es el concepto principal en Dialogflow ES. Una vez que se detecta una coincidencia con un intent, este puede mostrar una respuesta, recopilar parámetros (extracción de entidades) o activar código de webhook (entrega), por ejemplo, para recuperar datos de una base de datos.

Cuando un usuario final escribe o dice algo en un chatbot, lo que se conoce como expresión o declaración de usuario, Dialogflow ES asocia la expresión con el mejor intent de tu agente de Dialogflow, según las frases de entrenamiento. El modelo interno de aprendizaje automático de Dialogflow ES se entrenó con esas frases de entrenamiento.

Dialogflow ES funciona con un concepto llamado contexto. Al igual que un ser humano, Dialogflow ES puede recordar el contexto en un segundo y tercer turno. Así es como puede realizar un seguimiento de las declaraciones de usuarios anteriores.

Aquí encontrarás más información sobre los intents de Dialogflow.

Cómo modificar el intent de bienvenida predeterminado

Cuando creas un agente de Dialogflow nuevo, se crean automáticamente dos intents predeterminados. El intent de bienvenida predeterminado es el primer flujo al que accedes cuando inicias una conversación con el agente. El intent alternativo predeterminado es el flujo que obtendrás una vez que el agente no pueda comprenderte o no pueda hacer coincidir un intent con lo que acabas de decir.

Este es el mensaje de bienvenida para el intent de bienvenida predeterminado:

Usuario

Agente

¡Hola!

“Hola, soy el bot de preguntas frecuentes de Dialogflow y puedo responder preguntas sobre Dialogflow”.

“¿Qué te gustaría saber?”

  1. Haz clic en Intents > Intent de bienvenida predeterminado
  2. Desplázate hacia abajo hasta Respuestas.
  3. Borra todas las respuestas de texto.
  4. En la pestaña predeterminada, crea las siguientes 2 respuestas:
  • Hola, soy el bot de preguntas frecuentes de Dialogflow y puedo responder preguntas sobre Dialogflow. ¿Qué te gustaría saber?
  • Hola, soy el bot de preguntas frecuentes de Dialogflow. ¿Tienes preguntas sobre Dialogflow? ¿En qué puedo ayudarte?

La configuración debería ser similar a la de esta captura de pantalla.

Editar el intent de bienvenida predeterminado

  1. Haga clic en Guardar.
  2. Probemos este intent. Primero, podemos probarlo en el simulador de Dialogflow.Type: Hello. Se debería mostrar uno de estos mensajes:
  • Hola, soy el bot de preguntas frecuentes de Dialogflow y puedo responder preguntas sobre Dialogflow. ¿Qué te gustaría saber?
  • Hola, soy el bot de preguntas frecuentes de Dialogflow. ¿Tienes preguntas sobre Dialogflow? ¿En qué puedo ayudarte?

Modifica el intent de resguardo predeterminado

  1. Haz clic en Intents > Intent de resguardo predeterminado
  2. Desplázate hacia abajo hasta Respuestas.
  3. Borra todas las respuestas de texto.
  4. En la pestaña predeterminada, crea la siguiente respuesta:
  • Lamentablemente, no sé la respuesta a esta pregunta. ¿Revisaste nuestro sitio web? http://www.dialogflow.com?
  1. Haga clic en Guardar.

Conexión a una base de conocimiento en línea

Los conectores de conocimiento complementan los intents definidos. Analizan documentos de conocimiento para encontrar respuestas automáticas. (por ejemplo, preguntas frecuentes o artículos de archivos CSV, sitios web en línea o incluso archivos PDF). Para configurarlos, define una o más bases de conocimiento, que son colecciones de documentos de conocimiento.

Obtén más información sobre los conectores de conocimiento.

Probemos esto.

  1. Selecciona Conocimiento (beta) en el menú.

Base de conocimiento

  1. Haz clic en el botón azul derecho: Crear base de conocimiento
  2. Escribe como nombre de base de conocimiento. Consulta las Preguntas frecuentes sobre Dialogflow y presiona Guardar.
  3. Haz clic en el vínculo Create the first one.

Primera base de conocimiento

  1. Se abrirá una ventana.

Usa la siguiente configuración:

Nombre del documento: DialogflowFAQ Tipo de conocimiento: FAQ Tipo de MIME: text/html

  1. La URL desde la que cargamos los datos es la siguiente:

https://www.leeboonstra.dev/faqs/

  1. Haga clic en Crear.

Se creó una base de conocimiento:

Se creó la base de conocimiento

  1. Desplázate hacia abajo hasta la sección Responses y haz clic en Add Response (Agregar respuesta).

Crea las siguientes respuestas y presiona Guardar.

$Knowledge.Answer[1]
  1. Haz clic en Ver detalles.

Ver detalles

  1. Selecciona Habilitar la recarga automática para recuperar los cambios automáticamente cuando se actualice la página web de Preguntas frecuentes y presiona Guardar.

Aquí se mostrarán todas las preguntas frecuentes que implementaste en Dialogflow. ¡Es fácil!

Ten en cuenta que también podrías dirigir a un sitio web HTML en línea con Preguntas frecuentes para importar preguntas frecuentes a tu agente. Incluso es posible subir un PDF con un bloque de texto, y Dialogflow generará preguntas por sí mismo.

Ahora, las preguntas frecuentes deberían considerarse “extras”. para agregar a los agentes, junto a los flujos de intents. Las preguntas frecuentes de la base de conocimiento no pueden entrenar el modelo. Por lo tanto, si haces preguntas de una forma completamente diferente, es posible que no obtengas una coincidencia porque no se utiliza la comprensión del lenguaje natural (modelos de aprendizaje automático). Esta es la razón por la que, a veces, vale la pena convertir tus preguntas frecuentes en intents.

  1. Prueba las preguntas en el simulador de la derecha.
  2. Cuando todo funcione, vuelve a la app de Flutter y prueba el chat y el bot de voz con este contenido nuevo. Haz las preguntas que cargaste en Dialogflow.

Resultado

6. Felicitaciones

Felicitaciones, creaste correctamente tu primera app de Flutter con una integración de chatbot de Dialogflow. ¡Buen trabajo!

Temas abordados

  • Cómo crear un chatbot con Dialogflow Essentials
  • Cómo integrar Dialogflow en una app de Flutter
  • Cómo detectar intents de texto con Dialogflow
  • Cómo transmitir una voz a Dialogflow por medio del micrófono
  • Cómo usar el conector de la base de conocimiento

Próximos pasos

¿Te gustó este codelab? Consulta estos excelentes labs de Dialogflow.

¿Te interesa saber cómo compilamos el paquete gRPC de Dialogflow para Dart/Flutter?