Rilevamento dell'intent con il flusso di input audio

Questa pagina mostra come trasmettere in streaming l'input audio a una richiesta di rilevamento dell'intent utilizzando l'API. Dialogflow elabora l'audio e lo converte in testo prima di tentare una corrispondenza di intent. Questa conversione è nota come input audio, riconoscimento vocale, voce in testo o STT.

Prima di iniziare

Questa funzionalità è applicabile solo quando si utilizza l'API per le interazioni con l'utente finale. Se utilizzi un'integrazione, puoi saltare questa guida.

Prima di leggere questa guida, segui questi passaggi:

  1. Leggi le nozioni di base di Dialogflow.
  2. Esegui la procedura di configurazione.

Crea un agente

Se non hai ancora creato un agente, creane uno ora:

  1. Vai alla console Dialogflow ES.
  2. Se richiesto, accedi alla console di Dialogflow. Per ulteriori informazioni, consulta Panoramica della console Dialogflow.
  3. Fai clic su Crea agente nel menu della barra laterale sinistra. Se hai già altri agenti, fai clic sul nome dell'agente, scorri verso il basso e fai clic su Crea nuovo agente.
  4. Inserisci il nome, la lingua e il fuso orario predefinito dell'agente.
  5. Se hai già creato un progetto, inseriscilo. Se vuoi consentire alla console di Dialogflow di creare il progetto, seleziona Crea un nuovo progetto Google.
  6. Fai clic su pulsante Crea.

Importa il file di esempio nell'agente

I passaggi di questa guida fanno ipotesi sul tuo agente, pertanto devi import un agente preparato per questa guida. Durante l'importazione, questi passaggi utilizzano l'opzione restore, che sovrascrive tutte le impostazioni, gli intent e le entità dell'agente.

Per importare il file:

  1. Scarica il file room-booking-agent.zip.
  2. Vai alla console Dialogflow ES.
  3. Seleziona l'agente.
  4. Fai clic sul pulsante delle impostazioni accanto al nome dell'agente.
  5. Seleziona la scheda Esporta e importa.
  6. Seleziona Ripristina da file ZIP e segui le istruzioni per ripristinare il file ZIP che hai scaricato.

Nozioni di base sullo streaming

Il metodo streamingDetectIntent del tipo Session restituisce un oggetto streaming gRPC bidirezionale. I metodi disponibili per questo oggetto variano in base alla lingua, quindi consulta la documentazione di riferimento per la tua libreria client per i dettagli.

L'oggetto Flusso viene utilizzato per inviare e ricevere dati contemporaneamente. Con questo oggetto, il client trasmette il contenuto audio in Dialogflow e, contemporaneamente, ascolta un elemento StreamingDetectIntentResponse.

Il metodo streamingDetectIntent ha un parametro query_input.audio_config.single_utterance che influisce sul riconoscimento vocale:

  • Se il valore è false (impostazione predefinita), il riconoscimento vocale non cessa finché il client non chiude lo stream.
  • Se true, Dialogflow rileverà una singola espressione vocale nell'audio di input. Quando Dialogflow rileva che la voce dell'audio è stata interrotta o messa in pausa, cessa il riconoscimento vocale e invia un messaggio StreamingDetectIntentResponse con risultato del riconoscimento END_OF_SINGLE_UTTERANCE al tuo client. Qualsiasi audio inviato a Dialogflow nello stream dopo la ricezione di END_OF_SINGLE_UTTERANCE viene ignorato da Dialogflow.

Nel flusso bidirezionale, un client può chiudere metà l'oggetto flusso per segnalare al server che non invierà altri dati. Ad esempio, in Java e Go, questo metodo è chiamato closeSend. È importante chiudere gli stream a metà (ma non interromperli) nelle seguenti situazioni:

  • Il client ha terminato l'invio dei dati.
  • Il tuo client è configurato con single_utterance impostato su true e riceve un StreamingDetectIntentResponse con risultato del riconoscimento di END_OF_SINGLE_UTTERANCE.

Dopo aver chiuso uno stream, il client deve avviare una nuova richiesta con un nuovo stream, se necessario.

Intento di rilevamento streaming

Gli esempi riportati di seguito utilizzano il metodo streamingDetectIntent del tipo Session per trasmettere audio in streaming.

Go

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

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 "", errors.New(fmt.Sprintf("Received 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

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.


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

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

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

Per eseguire l'autenticazione in Dialogflow, configura le Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

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: 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))

Linguaggi aggiuntivi

C#: segui le istruzioni di configurazione di C# nella pagina delle librerie client e poi consulta la documentazione di riferimento di Dialogflow per .NET.

PHP: segui le istruzioni per la configurazione dei file PHP nella pagina delle librerie client e consulta la documentazione di riferimento di Dialogflow per PHP.

Ruby: segui le istruzioni di configurazione di Ruby nella pagina delle librerie client e visita la documentazione di riferimento di Dialogflow per Ruby.

Esempi

Consulta la pagina degli esempi per conoscere le best practice relative allo streaming dal microfono di un browser a Dialogflow.