Reconocimiento de intenciones a partir de contenido de voz mediante el SDK de Voz para C#

El SDK de Voz de Cognitive Services se integra con Language Understanding Intelligent Service (LUIS) para proporcionar un reconocimiento de la intención. Una intención es algo que el usuario quiere hacer: reservar un vuelo, comprobar el tiempo o hacer una llamada. El usuario puede utilizar cualquier término que le parezca natural. Mediante el aprendizaje automático, LUIS asigna las solicitudes de los usuarios a las intenciones que se hayan definido.

Nota

Una aplicación LUIS define las intenciones y entidades que desea reconocer. Es independiente de la aplicación C# que utiliza el servicio Voz. En este artículo, con la palabra "aplicación" se indica tanto la aplicación LUIS, como el código C#.

En esta guía, se utiliza el SDK de Voz para desarrollar una aplicación de consola C# que deriva las intenciones de las expresiones de los usuarios mediante el micrófono del dispositivo. Aprenderá a:

  • Crear un proyecto de Visual Studio que haga referencia al paquete NuGet del SDK de Voz
  • Crear una configuración de voz y obtener un reconocedor de intenciones
  • Obtener el modelo para la aplicación LUIS y agregar las intenciones que necesita
  • Especificar el idioma para el reconocimiento de voz
  • Reconocer la voz a partir de un archivo
  • Usar el reconocimiento asincrónico, continuo y controlado por eventos

Requisitos previos

Asegúrese de disponer de los siguientes elementos antes de empezar esta guía:

LUIS y voz

LUIS se integra con el servicio Voz para reconocer las intenciones a partir de contenido de voz. No necesita una suscripción al servicio Voz, solo LUIS.

LUIS usa tres tipos de claves:

Tipo de clave Propósito
Creación Le permite crear y modificar aplicaciones de LUIS mediante programación
Inicio Permite probar la aplicación de LUIS mediante el uso solo de texto.
Punto de conexión Autoriza el acceso a una aplicación de LUIS concreta

Para esta guía, necesitará el tipo de clave de punto de conexión. Esta guía utiliza la aplicación de LUIS Home Automation de ejemplo, que se puede crear siguiendo el inicio rápido Uso de automatización del hogar compilada previamente. Si ha creado su propia aplicación de LUIS, puede usarla si lo prefiere.

Al crear una aplicación LUIS, el propio LUIS genera automáticamente una clave de inicio para que pueda probarla aplicación mediante consultas de texto. Esta clave no permite la integración del servicio de voz y no funcionará con esta guía. Cree un recurso de LUIS en el panel de Azure y asígnelo a la aplicación de LUIS. Puede usar el nivel de suscripción gratis para esta guía.

Después de crear el recurso de LUIS en el panel de Azure, inicie sesión en el portal de LUIS, elija la aplicación en la página My Apps (Mis aplicaciones) y, después, cambie a la página Manage (Administrar) de la aplicación. Por último, seleccione Keys and Endpoints (Claves y puntos de conexión) en la barra lateral.

Configuración de los puntos de conexión y claves del portal de LUIS

En la página Keys and Endpoint settings (Configuración de claves y puntos de conexión):

  1. Desplácese hacia abajo hasta la sección Resources and Keys (Recursos y claves) y seleccione Assign resource (Asignar recurso).

  2. En el cuadro de diálogo Assign a key to your app (Asignar una clave a la aplicación), realices los siguientes cambios:

    • En Tenant (Inquilino), elija Microsoft.
    • En Subscription Name (Nombre de suscripción), elija la suscripción de Azure que contiene el recurso de LUIS que desea usar.
    • En Key (Clave), elija el recurso de LUIS que desea usar con la aplicación.

    En unos instantes, la nueva suscripción aparecerá en la tabla en la parte inferior de la página.

  3. Seleccione el icono situado junto a una clave para copiarla al Portapapeles. (Puede usar cualquiera de las claves).

Claves de suscripción de la aplicación LUIS

Creación de un proyecto de contenido de voz en Visual Studio

Para crear un proyecto de Visual Studio para el desarrollo de Windows, debe crear el proyecto, configurar Visual Studio para el desarrollo de escritorio de .NET, instalar el SDK de Voz y elegir la arquitectura de destino.

Creación del proyecto e incorporación de la carga de trabajo

Para empezar, cree el proyecto en Visual Studio y asegúrese de que Visual Studio está configurado para el desarrollo de escritorio de .NET:

  1. Abra Visual Studio 2019.

  2. En la ventana Inicio, seleccione Crear un proyecto.

  3. En la ventana Crear un proyecto, elija Aplicación de consola (.NET Framework) y seleccione Siguiente.

  4. En la ventana Configure su nuevo proyecto, escriba helloworld en Nombre del proyecto, elija o cree la ruta de acceso del directorio en Ubicación y seleccione Crear.

  5. En la barra de menús de Visual Studio, seleccione Herramientas > Obtener herramientas y características, que abre el Instalador de Visual Studio y muestra el cuadro de diálogo Modificando.

  6. Compruebe si la carga de trabajo Desarrollo de escritorio de .NET está disponible. Si la carga de trabajo aún no se ha instalado, active la casilla que hay al lado y seleccione Modificar para iniciar la instalación. La descarga e instalación pueden tardar unos minutos.

    Si la casilla que está junto a Desarrollo de escritorio de .NET ya está seleccionada, seleccione Cerrar para salir del cuadro de diálogo.

    Habilitación del desarrollo de escritorio .NET

  7. Cierre el Instalador de Visual Studio.

Instalación de Speech SDK

El siguiente paso consiste en instalar el paquete NuGet del SDK de Voz para que pueda hacer referencia a él en el código.

  1. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto helloworld y seleccione Administrar paquetes NuGet para mostrar el Administrador de paquetes NuGet.

    Administrador de paquetes de NuGet

  2. En la esquina superior derecha, busque el cuadro desplegable Origen del paquete y asegúrese de que nuget.org está seleccionado.

  3. En la esquina superior izquierda, seleccione Examinar.

  4. En el cuadro de búsqueda, escriba Microsoft.CognitiveServices.Speech y seleccione Entrar.

  5. En los resultados de la búsqueda, seleccione el paquete Microsoft.CognitiveServices.Speech y, después, seleccione Instalar para instalar la versión estable más reciente.

    Instalación del paquete NuGet Microsoft.CognitiveServices.Speech

  6. Acepte todos los contratos y licencias para iniciar la instalación.

    Después de instalar el paquete aparecerá una confirmación en la ventana Consola del administrador de paquetes.

Elección de la arquitectura de destino

Ahora, para compilar y ejecutar la aplicación de consola, cree una configuración de plataforma que coincida con la arquitectura del equipo.

  1. En la barra de menús, seleccione Compilar > Administrador de configuración. Aparecerá el cuadro de diálogo Administrador de configuración.

    Cuadro de diálogo Administrador de configuración

  2. En el cuadro desplegable Active solution platform (Plataforma de soluciones activas), seleccione Nuevo. Aparecerá el cuadro de diálogo Nueva plataforma de solución.

  3. En el cuadro desplegable escriba o seleccione la nueva plataforma:

    • Si está ejecutando Windows de 64 bits, seleccione x64.
    • Si está ejecutando Windows de 32 bits, seleccione x86.
  4. Seleccione Aceptar y, después, Cerrar.

Agregar el código

Después, agregue al código al proyecto.

  1. En el Explorador de soluciones, abra el archivo Program.cs.

  2. Reemplace el bloque de sentencias using del principio del archivo por las siguientes declaraciones:

    using System;
    using System.Threading.Tasks;
    using Microsoft.CognitiveServices.Speech;
    using Microsoft.CognitiveServices.Speech.Audio;
    using Microsoft.CognitiveServices.Speech.Intent;
    
  3. Reemplace el método Main() proporcionado por el siguiente equivalente asincrónico:

    public static async Task Main()
    {
        await RecognizeIntentAsync();
        Console.WriteLine("Please press Enter to continue.");
        Console.ReadLine();
    }
    
  4. Cree un método asincrónico vacío RecognizeIntentAsync(), tal como se muestra aquí:

    static async Task RecognizeIntentAsync()
    {
    }
    
  5. En el cuerpo del nuevo método, agregue este código:

    // Creates an instance of a speech config with specified subscription key
    // and service region. Note that in contrast to other services supported by
    // the Cognitive Services Speech SDK, the Language Understanding service
    // requires a specific subscription key from https://www.luis.ai/.
    // The Language Understanding service calls the required key 'endpoint key'.
    // Once you've obtained it, replace with below with your own Language Understanding subscription key
    // and service region (e.g., "westus").
    // The default language is "en-us".
    var config = SpeechConfig.FromSubscription("YourLanguageUnderstandingSubscriptionKey", "YourLanguageUnderstandingServiceRegion");
    
    // Creates an intent recognizer using microphone as audio input.
    using (var recognizer = new IntentRecognizer(config))
    {
        // Creates a Language Understanding model using the app id, and adds specific intents from your model
        var model = LanguageUnderstandingModel.FromAppId("YourLanguageUnderstandingAppId");
        recognizer.AddIntent(model, "YourLanguageUnderstandingIntentName1", "id1");
        recognizer.AddIntent(model, "YourLanguageUnderstandingIntentName2", "id2");
        recognizer.AddIntent(model, "YourLanguageUnderstandingIntentName3", "any-IntentId-here");
    
        // Starts recognizing.
        Console.WriteLine("Say something...");
    
        // Starts intent recognition, and returns after a single utterance is recognized. The end of a
        // single utterance is determined by listening for silence at the end or until a maximum of 15
        // seconds of audio is processed.  The task returns the recognition text as result. 
        // Note: Since RecognizeOnceAsync() returns only a single utterance, it is suitable only for single
        // shot recognition like command or query. 
        // For long-running multi-utterance recognition, use StartContinuousRecognitionAsync() instead.
        var result = await recognizer.RecognizeOnceAsync().ConfigureAwait(false);
    
        // Checks result.
        if (result.Reason == ResultReason.RecognizedIntent)
        {
            Console.WriteLine($"RECOGNIZED: Text={result.Text}");
            Console.WriteLine($"    Intent Id: {result.IntentId}.");
            Console.WriteLine($"    Language Understanding JSON: {result.Properties.GetProperty(PropertyId.LanguageUnderstandingServiceResponse_JsonResult)}.");
        }
        else if (result.Reason == ResultReason.RecognizedSpeech)
        {
            Console.WriteLine($"RECOGNIZED: Text={result.Text}");
            Console.WriteLine($"    Intent not recognized.");
        }
        else if (result.Reason == ResultReason.NoMatch)
        {
            Console.WriteLine($"NOMATCH: Speech could not be recognized.");
        }
        else if (result.Reason == ResultReason.Canceled)
        {
            var cancellation = CancellationDetails.FromResult(result);
            Console.WriteLine($"CANCELED: Reason={cancellation.Reason}");
    
            if (cancellation.Reason == CancellationReason.Error)
            {
                Console.WriteLine($"CANCELED: ErrorCode={cancellation.ErrorCode}");
                Console.WriteLine($"CANCELED: ErrorDetails={cancellation.ErrorDetails}");
                Console.WriteLine($"CANCELED: Did you update the subscription info?");
            }
        }
    }
    
  6. Reemplace los marcadores de posición en este método por su clave de suscripción, región e identificador de aplicación de LUIS, como se indica a continuación.

    Marcador de posición Reemplazar por
    YourLanguageUnderstandingSubscriptionKey La clave de punto de conexión de LUIS. Una vez más, este elemento se debe obtener en el panel de Azure, no una "clave de inicio". Se puede encontrar en la página Keys and Endpoints (Claves y puntos de conexión), (en Manage [Administrar]) en el portal de LUIS.
    YourLanguageUnderstandingServiceRegion El identificador corto para la región en la que se encuentra la suscripción a LUIS, como westus para Oeste de EE. UU. Consulte Regiones.
    YourLanguageUnderstandingAppId El id. de la aplicación LUIS. Se puede encontrar en la página Settings (Configuración) del portal de LUIS.

Con estos cambios realizados, puede crear (Control-Mayús-B) y ejecutar (F5) la aplicación de la guía. Cuando se le solicite, pruebe a decir "Apagar las luces" al micrófono del equipo. La aplicación muestra el resultado en la ventana de la consola.

Las secciones siguientes incluyen una explicación del código.

Creación de un reconocedor de intenciones

En primer lugar, es preciso crear una configuración de voz desde la región y la clave del punto de conexión de LUIS. Las configuraciones de voz se pueden utilizar para crear reconocedores para las distintas funcionalidades del SDK de Voz. La configuración de voz tiene varias formas de especificar la suscripción que se desea usar; aquí usamos FromSubscription, que toma la clave de suscripción y la región.

Nota

Utilice la clave y la región de su suscripción a LUIS, no de su suscripción al servicio de voz.

Después, cree un reconocedor de intenciones mediante new IntentRecognizer(config). Dado que la configuración ya sabe la suscripción que hay que utilizar, no es preciso volver a especificar la clave de suscripción y el punto de conexión al crear el reconocedor.

Importación de un modelo de LUIS y adición de intenciones

Ahora importe el modelo desde la aplicación LUIS mediante LanguageUnderstandingModel.FromAppId() y agregue las intenciones de LUIS que desee reconocer mediante el método AddIntent() del reconocedor. Estos dos pasos mejoran la precisión del reconocimiento de voz al indicar palabras que el usuario probablemente utilizará en sus solicitudes. No es preciso agregar todas las intenciones de la aplicación, salvo que se necesite reconocer todas en la aplicación.

Para agregar intenciones, es preciso especificar tres argumentos: el modelo de LUIS (que se ha creado y se llama model), el nombre de la intención y un identificador de la intención. La diferencia entre el identificador y el nombre es como sigue.

Argumento de AddIntent()  Propósito
intentName El nombre de la intención, tal como se define en la aplicación LUIS. Este valor debe coincidir exactamente con el nombre de la intención de LUIS.
intentID Identificador asignado a una intención reconocida por el SDK de Voz. Este valor puede ser el que desee; no es preciso que se corresponda con el nombre de la intención definido en la aplicación LUIS. Si se controlan varias intenciones con el mismo código, por ejemplo, se puede utilizar el mismo identificador para ellos.

La aplicación de LUIS Home Automation tiene dos intenciones: una para encender un dispositivo y otra para apagar un dispositivo. En las líneas siguientes se agregan estas intenciones al reconocedor; reemplace las tres líneas AddIntent del método RecognizeIntentAsync() por este código.

recognizer.AddIntent(model, "HomeAutomation.TurnOff", "off");
recognizer.AddIntent(model, "HomeAutomation.TurnOn", "on");

En lugar de agregar intenciones individuales, puede usar el método AddAllIntents para agregar todas las intenciones de un modelo al reconocedor.

Inicio del reconocimiento

Cuando haya creado el reconocedor y haya agregado las intenciones, puede empezar el reconocimiento. El SDK de Voz admite tanto reconocimiento al inicio como reconocimiento continuo.

Modo de reconocimiento Métodos para la llamada Resultado
Al inicio RecognizeOnceAsync() Devuelve la intención reconocida, si la hubiera, después de una expresión.
Continuo StartContinuousRecognitionAsync()
StopContinuousRecognitionAsync()
Reconoce varias expresiones; emite eventos (por ejemplo, IntermediateResultReceived) cuando los resultados están disponibles.

La aplicación utiliza el modo de reconocimiento al inicio y, por lo tanto, llama a RecognizeOnceAsync() para iniciarlo. El resultado es un objeto IntentRecognitionResult que contiene información sobre la intención reconocida. La respuesta JSON de LUIS se extrae mediante la siguiente expresión:

result.Properties.GetProperty(PropertyId.LanguageUnderstandingServiceResponse_JsonResult)

La aplicación no analiza el resultado de JSON. Solo muestra el texto JSON en la ventana de la consola.

Resultados individuales del reconocimiento de LUIS

Especificación de un idioma de reconocimiento

De forma predeterminada, LUIS reconoce las intenciones en idioma inglés de Estados Unidos (en-us). Al asignar un código de configuración regional a la propiedad SpeechRecognitionLanguage de la configuración de voz, puede reconocer las intenciones en otros idiomas. Por ejemplo, agregue config.SpeechRecognitionLanguage = "de-de"; en la aplicación antes de crear el reconocedor para reconocer las intenciones en idioma alemán. Para obtener más información, consulte Idiomas admitidos: LUIS.

Reconocimiento continuo desde un archivo

El código siguiente muestra dos funcionalidades adicionales de reconocimiento de intenciones mediante el SDK de Voz. La primera, mencionada anteriormente, es el reconocimiento continuo, donde el reconocedor emite eventos cuando los resultados están disponibles. Estos eventos los pueden procesar los controladores de eventos que proporcione. Con el reconocimiento continuo, se llama al método StartContinuousRecognitionAsync() del reconocedor para iniciar el reconocimiento, en lugar de a RecognizeOnceAsync().

La otra funcionalidad es leer el audio que contiene la voz que se va a procesar desde un archivo WAV. La implementación implica la creación de una configuración de audio que se puede utilizar al crear el reconocedor de intenciones. El archivo debe ser monocanal (mono) con una frecuencia de muestreo de 16 kHz.

Para probar estas características, elimine o marque como comentario el cuerpo del método RecognizeIntentAsync() y agregue el siguiente código en su lugar.

// Creates an instance of a speech config with specified subscription key
// and service region. Note that in contrast to other services supported by
// the Cognitive Services Speech SDK, the Language Understanding service
// requires a specific subscription key from https://www.luis.ai/.
// The Language Understanding service calls the required key 'endpoint key'.
// Once you've obtained it, replace with below with your own Language Understanding subscription key
// and service region (e.g., "westus").
var config = SpeechConfig.FromSubscription("YourLanguageUnderstandingSubscriptionKey", "YourLanguageUnderstandingServiceRegion");

// Creates an intent recognizer using file as audio input.
// Replace with your own audio file name.
using (var audioInput = AudioConfig.FromWavFileInput("whatstheweatherlike.wav"))
{
    using (var recognizer = new IntentRecognizer(config, audioInput))
    {
        // The TaskCompletionSource to stop recognition.
        var stopRecognition = new TaskCompletionSource<int>();

        // Creates a Language Understanding model using the app id, and adds specific intents from your model
        var model = LanguageUnderstandingModel.FromAppId("YourLanguageUnderstandingAppId");
        recognizer.AddIntent(model, "YourLanguageUnderstandingIntentName1", "id1");
        recognizer.AddIntent(model, "YourLanguageUnderstandingIntentName2", "id2");
        recognizer.AddIntent(model, "YourLanguageUnderstandingIntentName3", "any-IntentId-here");

        // Subscribes to events.
        recognizer.Recognizing += (s, e) => {
            Console.WriteLine($"RECOGNIZING: Text={e.Result.Text}");
        };

        recognizer.Recognized += (s, e) => {
            if (e.Result.Reason == ResultReason.RecognizedIntent)
            {
                Console.WriteLine($"RECOGNIZED: Text={e.Result.Text}");
                Console.WriteLine($"    Intent Id: {e.Result.IntentId}.");
                Console.WriteLine($"    Language Understanding JSON: {e.Result.Properties.GetProperty(PropertyId.LanguageUnderstandingServiceResponse_JsonResult)}.");
            }
            else if (e.Result.Reason == ResultReason.RecognizedSpeech)
            {
                Console.WriteLine($"RECOGNIZED: Text={e.Result.Text}");
                Console.WriteLine($"    Intent not recognized.");
            }
            else if (e.Result.Reason == ResultReason.NoMatch)
            {
                Console.WriteLine($"NOMATCH: Speech could not be recognized.");
            }
        };

        recognizer.Canceled += (s, e) => {
            Console.WriteLine($"CANCELED: Reason={e.Reason}");

            if (e.Reason == CancellationReason.Error)
            {
                Console.WriteLine($"CANCELED: ErrorCode={e.ErrorCode}");
                Console.WriteLine($"CANCELED: ErrorDetails={e.ErrorDetails}");
                Console.WriteLine($"CANCELED: Did you update the subscription info?");
            }

            stopRecognition.TrySetResult(0);
        };

        recognizer.SessionStarted += (s, e) => {
            Console.WriteLine("\n    Session started event.");
        };

        recognizer.SessionStopped += (s, e) => {
            Console.WriteLine("\n    Session stopped event.");
            Console.WriteLine("\nStop recognition.");
            stopRecognition.TrySetResult(0);
        };


        // Starts continuous recognition. Uses StopContinuousRecognitionAsync() to stop recognition.
        Console.WriteLine("Say something...");
        await recognizer.StartContinuousRecognitionAsync().ConfigureAwait(false);

        // Waits for completion.
        // Use Task.WaitAny to keep the task rooted.
        Task.WaitAny(new[] { stopRecognition.Task });

        // Stops recognition.
        await recognizer.StopContinuousRecognitionAsync().ConfigureAwait(false);
    }
}

Revise el código para incluir la clave del punto de conexión de LUIS, la región y el identificador de la aplicación y para agregar las intenciones de automatización de dispositivos del hogar, como antes. Cambie whatstheweatherlike.wav por el nombre del archivo de audio grabado. Luego realice la compilación, copie el archivo de audio en el directorio de compilación y ejecute la aplicación.

Por ejemplo, si dice "Apagar las luces", hace una pausa y, después, dice "Encender las luces" en el archivo de audio grabado, puede aparecer una salida en la consola similar a la siguiente:

Resultados del reconocimiento que hace LUIS de un archivo de audio

Código fuente de ejemplo

El equipo del SDK de Voz mantiene activamente un conjunto grande de ejemplos en un repositorio de código abierto. Para obtener el repositorio de código fuente de ejemplo, visite el SDK de Voz de Microsoft Cognitive Services en GitHub . Hay ejemplos para C#, C++, Java, Python, Objective-C, Swift, JavaScript, UWP, Unity y Xamarin.


GitHub

Busque el código de este artículo en la carpeta samples/csharp/sharedcontent/console.

Pasos siguientes