Mendeteksi intent dengan streaming input audio

Halaman ini menunjukkan cara melakukan streaming input audio ke permintaan intent deteksi menggunakan API. Dialogflow memproses audio dan mengubahnya menjadi teks sebelum mencoba pencocokan intent. Konversi ini disebut sebagai input audio, pengenalan ucapan, speech-to-text, atau STT.

Sebelum memulai

Fitur ini hanya berlaku jika menggunakan API untuk interaksi pengguna akhir. Jika Anda menggunakan integrasi, Anda dapat melewati panduan ini.

Anda harus melakukan hal berikut sebelum membaca panduan ini:

  1. Baca Dasar-dasar Dialogflow.
  2. Lakukan langkah-langkah penyiapan.

Membuat agen

Jika Anda belum membuat agen, buat agen sekarang:

  1. Buka Konsol Dialogflow ES.
  2. Jika diminta, login ke Konsol Dialogflow. Lihat Ringkasan konsol Dialogflow untuk mengetahui informasi selengkapnya.
  3. Klik Create Agent di menu sidebar kiri. (Jika sudah memiliki agen lain, klik nama agen, scroll ke bagian bawah, lalu klik Buat agen baru.)
  4. Masukkan nama agen, bahasa default, dan zona waktu default.
  5. Jika Anda sudah membuat project, masukkan project tersebut. Jika Anda ingin mengizinkan Konsol Dialogflow untuk membuat project, pilih Buat project Google baru.
  6. Klik tombol Buat.

Impor file contoh ke agen Anda

Langkah-langkah dalam panduan ini membuat asumsi tentang agen, sehingga Anda perlu impor agen yang disiapkan untuk panduan ini. Saat mengimpor, langkah-langkah ini menggunakan opsi pulihkan, yang menimpa semua setelan, intent, dan entity agen.

Untuk mengimpor file, ikuti langkah-langkah berikut:

  1. Unduh room-booking-agent.zip .
  2. Buka Konsol Dialogflow ES.
  3. Pilih agen Anda.
  4. Klik tombol setelan di samping nama agen.
  5. Pilih tab Export and Import.
  6. Pilih Pulihkan Dari Zip dan ikuti petunjuk untuk memulihkan file ZIP yang Anda download.

Dasar-dasar streaming

Session metode streamingDetectIntent jenis ini menampilkan objek streaming gRPC dua arah. Metode yang tersedia untuk objek ini bervariasi menurut bahasa, jadi lihat dokumentasi referensi untuk pustaka klien Anda untuk detailnya.

Objek streaming digunakan untuk mengirim dan menerima data secara serentak. Dengan menggunakan objek ini, klien Anda melakukan streaming konten audio ke Dialogflow, sembari memproses StreamingDetectIntentResponse secara serentak.

Metode streamingDetectIntent memiliki Parameter query_input.audio_config.single_utterance yang memengaruhi pengenalan ucapan:

  • Jika false (default), pengenalan ucapan tidak dihentikan sampai klien menutup streaming.
  • Jika true, Dialogflow akan mendeteksi satu ucapan lisan dalam audio input. Ketika Dialogflow mendeteksi bahwa suara audio telah berhenti atau dijeda, perangkat akan menghentikan pengenalan ucapan dan mengirimkan StreamingDetectIntentResponse dengan hasil pengenalan END_OF_SINGLE_UTTERANCE kepada klien. Audio apa pun yang dikirim ke Dialogflow pada streaming setelah penerimaan END_OF_SINGLE_UTTERANCE diabaikan oleh Dialogflow.

Dalam streaming dua arah, klien dapat menutup setengah objek aliran untuk memberi sinyal ke server bahwa server tidak akan mengirim lebih banyak data. Misalnya, di Java dan Go, metode ini disebut closeSend. Anda perlu menutup setengah (tetapi tidak membatalkan) streaming dalam situasi berikut:

  • Klien Anda telah selesai mengirim data.
  • Klien Anda dikonfigurasi dengan single_utterance disetel ke benar (true). dan menerima StreamingDetectIntentResponse dengan hasil pengenalan END_OF_SINGLE_UTTERANCE.

Setelah menutup streaming, klien Anda harus memulai permintaan baru dengan streaming baru sesuai kebutuhan.

Intent deteksi streaming

Contoh berikut menggunakan Session metode streamingDetectIntent jenis untuk melakukan streaming audio.

Go

Untuk mengautentikasi ke Dialogflow, siapkan Kredensial Default Aplikasi. Untuk informasi selengkapnya, lihat Menyiapkan autentikasi untuk lingkungan pengembangan lokal.

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

Untuk mengautentikasi ke Dialogflow, siapkan Kredensial Default Aplikasi. Untuk informasi selengkapnya, lihat Menyiapkan autentikasi untuk lingkungan pengembangan lokal.


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

Untuk mengautentikasi ke Dialogflow, siapkan Kredensial Default Aplikasi. Untuk informasi selengkapnya, lihat Menyiapkan autentikasi untuk lingkungan pengembangan lokal.

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

Untuk mengautentikasi ke Dialogflow, siapkan Kredensial Default Aplikasi. Untuk informasi selengkapnya, lihat Menyiapkan autentikasi untuk lingkungan pengembangan lokal.

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

Bahasa tambahan

C#: Harap ikuti Petunjuk penyiapan C# di halaman library klien lalu kunjungi Dokumentasi referensi Dialogflow untuk .NET.

PHP: Harap ikuti Petunjuk penyiapan PHP di halaman library klien lalu kunjungi Dokumentasi referensi Dialogflow untuk PHP.

Ruby: Harap ikuti Petunjuk penyiapan Ruby di halaman library klien lalu kunjungi Dokumentasi referensi Dialogflow untuk Ruby.

Sampel

Lihat halaman contoh untuk mengetahui praktik terbaik tentang streaming dari mikrofon browser ke Dialogflow.