Detectar intents con transmisión de entrada de audio

En esta página se muestra cómo enviar audio a una solicitud de detección de intención mediante la API. Dialogflow procesa el audio y lo convierte en texto antes de intentar encontrar una coincidencia con una intención. Esta conversión se conoce como entrada de audio, reconocimiento de voz, transcripción de voz o STT.

Antes de empezar

Esta función solo se aplica cuando se usa la API para las interacciones con el usuario final. Si usas una integración, puedes saltarte esta guía.

Antes de leer esta guía, debes hacer lo siguiente:

  1. Consulta los conceptos básicos de Dialogflow.
  2. Sigue los pasos de configuración.

Crear un agente

Si aún no has creado un agente, hazlo ahora:

  1. Ve a la consola de Dialogflow ES.
  2. Si se te solicita, inicia sesión en la consola de Dialogflow. Para obtener más información, consulta el artículo Información general sobre la consola de Dialogflow.
  3. En el menú de la barra lateral de la izquierda, haz clic en Crear agente. Si ya tienes otros agentes, haz clic en el nombre del agente, desplázate hasta la parte inferior y haz clic en Crear nuevo agente.
  4. Introduce el nombre, el idioma predeterminado y la zona horaria predeterminada del agente.
  5. Si ya has creado un proyecto, accede a él. Si quieres permitir que la consola de Dialogflow cree el proyecto, selecciona Crear un proyecto de Google.
  6. Haz clic en el botón Crear.

Importar el archivo de ejemplo a tu agente

En los pasos de esta guía se presupone que tienes un agente, por lo que debes importar un agente preparado para esta guía. Al importar, estos pasos utilizan la opción Restaurar, que sobrescribe todos los ajustes, las intenciones y las entidades del agente.

Para importar el archivo, sigue estos pasos:

  1. Descarga el archivo room-booking-agent.zip.
  2. Ve a la consola de Dialogflow ES.
  3. Selecciona tu agente.
  4. Haz clic en el botón de configuración situado junto al nombre del agente.
  5. Selecciona la pestaña Exportar e importar.
  6. Selecciona Restaurar desde ZIP y sigue las instrucciones para restaurar el archivo ZIP que has descargado.

Conceptos básicos sobre el streaming

El método streamingDetectIntent del tipo Session devuelve un objeto de streaming bidireccional de gRPC. Los métodos disponibles para este objeto varían según el lenguaje, por lo que debes consultar la documentación de referencia de tu biblioteca de cliente para obtener más información.

El objeto de streaming se usa para enviar y recibir datos simultáneamente. Con este objeto, tu cliente transmite contenido de audio a Dialogflow mientras escucha simultáneamente una StreamingDetectIntentResponse.

El método streamingDetectIntent tiene un parámetro query_input.audio_config.single_utterance que afecta al reconocimiento de voz:

  • Si se usa false (valor predeterminado), el reconocimiento de voz no se detiene hasta que el cliente cierra el flujo.
  • Si true, Dialogflow detectará una sola expresión hablada en el audio de entrada. Cuando Dialogflow detecta que la voz del audio se ha detenido o pausado, deja de reconocer la voz y envía un StreamingDetectIntentResponse con un resultado de reconocimiento de END_OF_SINGLE_UTTERANCE a tu cliente. Dialogflow ignora el audio que se envía a Dialogflow en el flujo después de recibir END_OF_SINGLE_UTTERANCE.

En el streaming bidireccional, un cliente puede cerrar parcialmente el objeto de flujo para indicar al servidor que no enviará más datos. Por ejemplo, en Java y Go, este método se llama closeSend. Es importante cerrar los flujos a medias (pero no cancelarlos) en las siguientes situaciones:

  • Tu cliente ha terminado de enviar datos.
  • Tu cliente tiene el valor single_utterance configurado como true y recibe un StreamingDetectIntentResponse con un resultado de reconocimiento de END_OF_SINGLE_UTTERANCE.

Después de cerrar una emisión, tu cliente debe iniciar una nueva solicitud con una nueva emisión según sea necesario.

Detectar intent en streaming

En los siguientes ejemplos se usa el método streamingDetectIntent del tipo Session para transmitir audio.

Go

Para autenticarte en Dialogflow, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

func DetectIntentStream(projectID, sessionID, audioFile, languageCode string) (string, error) {
	ctx := context.Background()

	sessionClient, err := dialogflow.NewSessionsClient(ctx)
	if err != nil {
		return "", err
	}
	defer sessionClient.Close()

	if projectID == "" || sessionID == "" {
		return "", fmt.Errorf("detect.DetectIntentStream empty project (%s) or session (%s)", projectID, sessionID)
	}

	sessionPath := fmt.Sprintf("projects/%s/agent/sessions/%s", projectID, sessionID)

	// In this example, we hard code the encoding and sample rate for simplicity.
	audioConfig := dialogflowpb.InputAudioConfig{AudioEncoding: dialogflowpb.AudioEncoding_AUDIO_ENCODING_LINEAR_16, SampleRateHertz: 16000, LanguageCode: languageCode}

	queryAudioInput := dialogflowpb.QueryInput_AudioConfig{AudioConfig: &audioConfig}

	queryInput := dialogflowpb.QueryInput{Input: &queryAudioInput}

	streamer, err := sessionClient.StreamingDetectIntent(ctx)
	if err != nil {
		return "", err
	}

	f, err := os.Open(audioFile)
	if err != nil {
		return "", err
	}

	defer f.Close()

	go func() {
		audioBytes := make([]byte, 1024)

		request := dialogflowpb.StreamingDetectIntentRequest{Session: sessionPath, QueryInput: &queryInput}
		err = streamer.Send(&request)
		if err != nil {
			log.Fatal(err)
		}

		for {
			_, err := f.Read(audioBytes)
			if err == io.EOF {
				streamer.CloseSend()
				break
			}
			if err != nil {
				log.Fatal(err)
			}

			request = dialogflowpb.StreamingDetectIntentRequest{InputAudio: audioBytes}
			err = streamer.Send(&request)
			if err != nil {
				log.Fatal(err)
			}
		}
	}()

	var queryResult *dialogflowpb.QueryResult

	for {
		response, err := streamer.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}

		recognitionResult := response.GetRecognitionResult()
		transcript := recognitionResult.GetTranscript()
		log.Printf("Recognition transcript: %s\n", transcript)

		queryResult = response.GetQueryResult()
	}

	fulfillmentText := queryResult.GetFulfillmentText()
	return fulfillmentText, nil
}

Java

Para autenticarte en Dialogflow, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.


import com.google.api.gax.rpc.ApiException;
import com.google.api.gax.rpc.BidiStream;
import com.google.cloud.dialogflow.v2.AudioEncoding;
import com.google.cloud.dialogflow.v2.InputAudioConfig;
import com.google.cloud.dialogflow.v2.QueryInput;
import com.google.cloud.dialogflow.v2.QueryResult;
import com.google.cloud.dialogflow.v2.SessionName;
import com.google.cloud.dialogflow.v2.SessionsClient;
import com.google.cloud.dialogflow.v2.StreamingDetectIntentRequest;
import com.google.cloud.dialogflow.v2.StreamingDetectIntentResponse;
import com.google.protobuf.ByteString;
import java.io.FileInputStream;
import java.io.IOException;

class DetectIntentStream {

  // DialogFlow API Detect Intent sample with audio files processes as an audio stream.
  static void detectIntentStream(String projectId, String audioFilePath, String sessionId)
      throws IOException, ApiException {
    // String projectId = "YOUR_PROJECT_ID";
    // String audioFilePath = "path_to_your_audio_file";
    // Using the same `sessionId` between requests allows continuation of the conversation.
    // String sessionId = "Identifier of the DetectIntent session";

    // Instantiates a client
    try (SessionsClient sessionsClient = SessionsClient.create()) {
      // Set the session name using the sessionId (UUID) and projectID (my-project-id)
      SessionName session = SessionName.of(projectId, sessionId);

      // Instructs the speech recognizer how to process the audio content.
      // Note: hard coding audioEncoding and sampleRateHertz for simplicity.
      // Audio encoding of the audio content sent in the query request.
      InputAudioConfig inputAudioConfig =
          InputAudioConfig.newBuilder()
              .setAudioEncoding(AudioEncoding.AUDIO_ENCODING_LINEAR_16)
              .setLanguageCode("en-US") // languageCode = "en-US"
              .setSampleRateHertz(16000) // sampleRateHertz = 16000
              .build();

      // Build the query with the InputAudioConfig
      QueryInput queryInput = QueryInput.newBuilder().setAudioConfig(inputAudioConfig).build();

      // Create the Bidirectional stream
      BidiStream<StreamingDetectIntentRequest, StreamingDetectIntentResponse> bidiStream =
          sessionsClient.streamingDetectIntentCallable().call();

      // The first request must **only** contain the audio configuration:
      bidiStream.send(
          StreamingDetectIntentRequest.newBuilder()
              .setSession(session.toString())
              .setQueryInput(queryInput)
              .build());

      try (FileInputStream audioStream = new FileInputStream(audioFilePath)) {
        // Subsequent requests must **only** contain the audio data.
        // Following messages: audio chunks. We just read the file in fixed-size chunks. In reality
        // you would split the user input by time.
        byte[] buffer = new byte[4096];
        int bytes;
        while ((bytes = audioStream.read(buffer)) != -1) {
          bidiStream.send(
              StreamingDetectIntentRequest.newBuilder()
                  .setInputAudio(ByteString.copyFrom(buffer, 0, bytes))
                  .build());
        }
      }

      // Tell the service you are done sending data
      bidiStream.closeSend();

      for (StreamingDetectIntentResponse response : bidiStream) {
        QueryResult queryResult = response.getQueryResult();
        System.out.println("====================");
        System.out.format("Intent Display Name: %s\n", queryResult.getIntent().getDisplayName());
        System.out.format("Query Text: '%s'\n", queryResult.getQueryText());
        System.out.format(
            "Detected Intent: %s (confidence: %f)\n",
            queryResult.getIntent().getDisplayName(), queryResult.getIntentDetectionConfidence());
        System.out.format(
            "Fulfillment Text: '%s'\n",
            queryResult.getFulfillmentMessagesCount() > 0
                ? queryResult.getFulfillmentMessages(0).getText()
                : "Triggered Default Fallback Intent");
      }
    }
  }
}

Node.js

Para autenticarte en Dialogflow, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

const fs = require('fs');
const util = require('util');
const {Transform, pipeline} = require('stream');
const {struct} = require('pb-util');

const pump = util.promisify(pipeline);
// Imports the Dialogflow library
const dialogflow = require('@google-cloud/dialogflow');

// Instantiates a session client
const sessionClient = new dialogflow.SessionsClient();

// The path to the local file on which to perform speech recognition, e.g.
// /path/to/audio.raw const filename = '/path/to/audio.raw';

// The encoding of the audio file, e.g. 'AUDIO_ENCODING_LINEAR_16'
// const encoding = 'AUDIO_ENCODING_LINEAR_16';

// The sample rate of the audio file in hertz, e.g. 16000
// const sampleRateHertz = 16000;

// The BCP-47 language code to use, e.g. 'en-US'
// const languageCode = 'en-US';
const sessionPath = sessionClient.projectAgentSessionPath(
  projectId,
  sessionId
);

const initialStreamRequest = {
  session: sessionPath,
  queryInput: {
    audioConfig: {
      audioEncoding: encoding,
      sampleRateHertz: sampleRateHertz,
      languageCode: languageCode,
    },
  },
};

// Create a stream for the streaming request.
const detectStream = sessionClient
  .streamingDetectIntent()
  .on('error', console.error)
  .on('data', data => {
    if (data.recognitionResult) {
      console.log(
        `Intermediate transcript: ${data.recognitionResult.transcript}`
      );
    } else {
      console.log('Detected intent:');

      const result = data.queryResult;
      // Instantiates a context client
      const contextClient = new dialogflow.ContextsClient();

      console.log(`  Query: ${result.queryText}`);
      console.log(`  Response: ${result.fulfillmentText}`);
      if (result.intent) {
        console.log(`  Intent: ${result.intent.displayName}`);
      } else {
        console.log('  No intent matched.');
      }
      const parameters = JSON.stringify(struct.decode(result.parameters));
      console.log(`  Parameters: ${parameters}`);
      if (result.outputContexts && result.outputContexts.length) {
        console.log('  Output contexts:');
        result.outputContexts.forEach(context => {
          const contextId =
            contextClient.matchContextFromProjectAgentSessionContextName(
              context.name
            );
          const contextParameters = JSON.stringify(
            struct.decode(context.parameters)
          );
          console.log(`    ${contextId}`);
          console.log(`      lifespan: ${context.lifespanCount}`);
          console.log(`      parameters: ${contextParameters}`);
        });
      }
    }
  });

// Write the initial stream request to config for audio input.
detectStream.write(initialStreamRequest);

// Stream an audio file from disk to the Conversation API, e.g.
// "./resources/audio.raw"
await pump(
  fs.createReadStream(filename),
  // Format the audio stream into the request format.
  new Transform({
    objectMode: true,
    transform: (obj, _, next) => {
      next(null, {inputAudio: obj});
    },
  }),
  detectStream
);

Python

Para autenticarte en Dialogflow, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

def detect_intent_stream(project_id, session_id, audio_file_path, language_code):
    """Returns the result of detect intent with streaming audio as input.

    Using the same `session_id` between requests allows continuation
    of the conversation."""
    from google.cloud import dialogflow

    session_client = dialogflow.SessionsClient()

    # Note: hard coding audio_encoding and sample_rate_hertz for simplicity.
    audio_encoding = dialogflow.AudioEncoding.AUDIO_ENCODING_LINEAR_16
    sample_rate_hertz = 16000

    session_path = session_client.session_path(project_id, session_id)
    print("Session path: {}\n".format(session_path))

    def request_generator(audio_config, audio_file_path):
        query_input = dialogflow.QueryInput(audio_config=audio_config)

        # The first request contains the configuration.
        yield dialogflow.StreamingDetectIntentRequest(
            session=session_path, query_input=query_input
        )

        # Here we are reading small chunks of audio data from a local
        # audio file.  In practice these chunks should come from
        # an audio input device.
        with open(audio_file_path, "rb") as audio_file:
            while True:
                chunk = audio_file.read(4096)
                if not chunk:
                    break
                # The later requests contains audio data.
                yield dialogflow.StreamingDetectIntentRequest(input_audio=chunk)

    audio_config = dialogflow.InputAudioConfig(
        audio_encoding=audio_encoding,
        language_code=language_code,
        sample_rate_hertz=sample_rate_hertz,
    )

    requests = request_generator(audio_config, audio_file_path)
    responses = session_client.streaming_detect_intent(requests=requests)

    print("=" * 20)
    for response in responses:
        print(
            'Intermediate transcript: "{}".'.format(
                response.recognition_result.transcript
            )
        )
        # Note: Since Python gRPC doesn't have closeSend method, to stop processing the audio after result is recognized,
        # you may close the channel manually to prevent further iteration.
        # Keep in mind that if there is a silence chunk in the audio, part after it might be missed because of early teardown.
        # https://cloud.google.com/dialogflow/es/docs/how/detect-intent-stream#streaming_basics
        if response.recognition_result.is_final:
            session_client.transport.close()
            break

    # Note: The result from the last response is the final transcript along
    # with the detected content.
    query_result = response.query_result

    print("=" * 20)
    print("Query text: {}".format(query_result.query_text))
    print(
        "Detected intent: {} (confidence: {})\n".format(
            query_result.intent.display_name, query_result.intent_detection_confidence
        )
    )
    print("Fulfillment text: {}\n".format(query_result.fulfillment_text))

Idiomas adicionales

C#: Sigue las instrucciones de configuración de C# en la página de bibliotecas de cliente y, a continuación, consulta la documentación de referencia de Dialogflow para .NET.

PHP Sigue las instrucciones de configuración de PHP en la página de bibliotecas de cliente y, a continuación, consulta la documentación de referencia de Dialogflow para PHP.

Ruby: Sigue las instrucciones de configuración de Ruby en la página de bibliotecas de cliente y, a continuación, consulta la documentación de referencia de Dialogflow para Ruby.

Ejemplos

Consulta la página de ejemplos para ver las prácticas recomendadas sobre la transmisión desde un micrófono del navegador a Dialogflow.