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

El SDK de voz de los servicios Azure AI se integra con el Servicio de comprensión del lenguaje (LUIS) para proporcionar reconocimiento de intenciones. 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. LUIS asigna las solicitudes de los usuarios a las intenciones definidas.

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 dos tipos de claves:

Tipo de clave Propósito
Creación Le permite crear y modificar aplicaciones de LUIS mediante programación
Predicción Se usa para acceder a la aplicación de LUIS en tiempo de ejecución

Para esta guía, necesita el tipo de clave de predicció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 creación para que pueda probar la aplicación mediante consultas de texto. Esta clave no permite la integración del servicio de voz y no funciona 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 Recursos de Azure en la barra lateral.

Shows a screenshot of the LUIS portal keys and endpoint settings.

En la página Recursos de Azure:

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

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

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.

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 no está instalada, 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.

    Enable .NET desktop development

  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.

    NuGet Package Manager

  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.

    Install Microsoft.CognitiveServices.Speech NuGet package

  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.

    Configuration Manager dialog box

  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 recurso, región e id. de la aplicación de LUIS, tal como se indica a continuación.

    Marcador de posición Reemplazar por
    YourLanguageUnderstandingSubscriptionKey La clave de recurso de LUIS. Una vez más, este elemento se debe obtener en el panel de Azure. Se puede encontrar en la página Recursos de Azure, (en Administrar) en el portal de LUIS.
    YourLanguageUnderstandingServiceRegion El identificador corto para la región en la que se encuentra el recurso de 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 de predicció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 el recurso que se quiere usar; aquí usamos FromSubscription, que toma la clave de recurso y la región.

Nota

Utilice la clave y la región del recurso de LUIS, no del recurso de Voz.

Después, cree un reconocedor de intenciones mediante new IntentRecognizer(config). Dado que la configuración ya sabe el recurso que hay que utilizar, no es preciso volver a especificar la clave 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 (denominado 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 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 el reconocimiento continuo como el de una sola emisión.

Modo de reconocimiento Métodos para la llamada Resultado
Emisión única 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 emisión única y, por lo tanto, llama a RecognizeOnceAsync() para iniciar el reconocimiento. 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.

Single LUIS recognition results

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 más 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 se procesan mediante 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("YourAudioFile.wav"))
{
    using (var recognizer = new IntentRecognizer(config, audioInput))
    {
        // The TaskCompletionSource to stop recognition.
        var stopRecognition = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);

        // 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.
        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 de predicció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:

Audio file LUIS recognition results

El equipo del SDK de Voz mantiene activamente un conjunto grande de ejemplos en un repositorio de código abierto. Para ver el repositorio del código fuente de muestra, consulte Azure AI Speech SDK en GitHub. Hay ejemplos para C#, C++, Java, Python, Objective-C, Swift, JavaScript, UWP, Unity y Xamarin. Busque el código de este artículo en la carpeta samples/csharp/sharedcontent/console.

Pasos siguientes

Inicio rápido: Reconocimiento de voz a través de un micrófono