Skip to content

Commit

Permalink
samples: Update streaming sample to use non-deprecated method (#1413)
Browse files Browse the repository at this point in the history
  • Loading branch information
nnegrey authored and Shabirmean committed Nov 15, 2022
1 parent e364ac7 commit da73918
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@

package com.example.dialogflow;


// [START dialogflow_detect_intent_streaming]
// Imports the Google Cloud client library

import com.google.api.gax.rpc.ApiStreamObserver;
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;
Expand All @@ -29,138 +28,77 @@
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.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.io.IOException;

/**
* DialogFlow API Detect Intent sample with audio files processes as an audio stream.
*/
public class DetectIntentStream {
// [START dialogflow_detect_intent_streaming]
class DetectIntentStream {

/**
* Returns the result of detect intent with streaming audio as input.
*
* Using the same `session_id` between requests allows continuation of the conversation.
*
* @param projectId Project/Agent Id.
* @param audioFilePath The audio file to be processed.
* @param sessionId Identifier of the DetectIntent session.
* @param languageCode Language code of the query.
* @return The List of StreamingDetectIntentResponses to the input audio inputs.
*/
public static List<StreamingDetectIntentResponse> detectIntentStream(
String projectId,
String audioFilePath,
String sessionId,
String languageCode) throws Throwable {
// Start bi-directional StreamingDetectIntent stream.
final CountDownLatch notification = new CountDownLatch(1);
final List<Throwable> responseThrowables = new ArrayList<>();
final List<StreamingDetectIntentResponse> responses = new ArrayList<>();
static void detectIntentStream(String projectId, String audioFilePath, String sessionId) {
// 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);
System.out.println("Session Path: " + session.toString());

// 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.
AudioEncoding audioEncoding = AudioEncoding.AUDIO_ENCODING_LINEAR_16;
int sampleRateHertz = 16000;

// Instructs the speech recognizer how to process the audio content.
InputAudioConfig inputAudioConfig = InputAudioConfig.newBuilder()
.setAudioEncoding(audioEncoding) // audioEncoding = AudioEncoding.AUDIO_ENCODING_LINEAR_16
.setLanguageCode(languageCode) // languageCode = "en-US"
.setSampleRateHertz(sampleRateHertz) // sampleRateHertz = 16000
.setAudioEncoding(AudioEncoding.AUDIO_ENCODING_LINEAR_16)
.setLanguageCode("en-US") // languageCode = "en-US"
.setSampleRateHertz(16000) // sampleRateHertz = 16000
.build();

ApiStreamObserver<StreamingDetectIntentResponse> responseObserver =
new ApiStreamObserver<StreamingDetectIntentResponse>() {
@Override
public void onNext(StreamingDetectIntentResponse response) {
// Do something when receive a response
responses.add(response);
}

@Override
public void onError(Throwable t) {
// Add error-handling
responseThrowables.add(t);
}

@Override
public void onCompleted() {
// Do something when complete.
notification.countDown();
}
};

// Performs the streaming detect intent callable request
ApiStreamObserver<StreamingDetectIntentRequest> requestObserver =
sessionsClient.streamingDetectIntentCallable().bidiStreamingCall(responseObserver);

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

try (FileInputStream audioStream = new FileInputStream(audioFilePath)) {
// The first request contains the configuration
StreamingDetectIntentRequest request = StreamingDetectIntentRequest.newBuilder()
.setSession(session.toString())
.setQueryInput(queryInput)
.build();
// Create the Bidirectional stream
BidiStream<StreamingDetectIntentRequest, StreamingDetectIntentResponse> bidiStream =
sessionsClient.streamingDetectIntentCallable().call();

// Make the first request
requestObserver.onNext(request);
// 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) {
requestObserver.onNext(
bidiStream.send(
StreamingDetectIntentRequest.newBuilder()
.setInputAudio(ByteString.copyFrom(buffer, 0, bytes))
.build());
}
} catch (RuntimeException e) {
// Cancel stream.
requestObserver.onError(e);
}
// Half-close the stream.
requestObserver.onCompleted();
// Wait for the final response (without explicit timeout).
notification.await();
// Process errors/responses.
if (!responseThrowables.isEmpty()) {
throw responseThrowables.get(0);
}
if (responses.isEmpty()) {
throw new RuntimeException("No response from Dialogflow.");
}

for (StreamingDetectIntentResponse response : responses) {
if (response.hasRecognitionResult()) {
System.out.format(
"Intermediate transcript: '%s'\n", response.getRecognitionResult().getTranscript());
}
}
// Tell the service you are done sending data
bidiStream.closeSend();

// Display the last query result
QueryResult queryResult = responses.get(responses.size() - 1).getQueryResult();
System.out.println("====================");
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.getFulfillmentText());
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.getFulfillmentText());

return responses;
}
} catch (IOException e) {
e.printStackTrace();
}
}
// [END dialogflow_detect_intent_streaming]
}
// [END dialogflow_detect_intent_streaming]
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@

package com.example.dialogflow;

import static org.junit.Assert.assertTrue;

import com.google.cloud.dialogflow.v2.StreamingDetectIntentResponse;
import static org.junit.Assert.assertThat;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.List;

import org.hamcrest.CoreMatchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -37,32 +35,35 @@
@SuppressWarnings("checkstyle:abbreviationaswordinname")
public class DetectIntentStreamIT {

private ByteArrayOutputStream bout;

private static String audioFilePath = "resources/book_a_room.wav";
private static String PROJECT_ID = System.getenv().get("GOOGLE_CLOUD_PROJECT");
private static String SESSION_ID = "fake_session_for_testing";
private static String LANGUAGE_CODE = "en-US";

@Before
public void setUp() {
System.setOut(new PrintStream(new ByteArrayOutputStream()));
bout = new ByteArrayOutputStream();
System.setOut(new PrintStream(bout));
}

@After
public void tearDown() {
System.setOut(null);
bout.reset();
}

@Test
public void testStreamingDetectIntentCallable() throws Throwable {
List<StreamingDetectIntentResponse> response = DetectIntentStream.detectIntentStream(
PROJECT_ID, audioFilePath, SESSION_ID, LANGUAGE_CODE);
assertTrue(response.size() > 0);
assertTrue(response.stream().anyMatch(i -> i
.getQueryResult()
.getIntent()
.getDisplayName().equals("room.reservation")));
assertTrue(response.stream().anyMatch(i -> i
.getRecognitionResult()
.getTranscript().contains("book")));
public void testStreamingDetectIntentCallable() {
DetectIntentStream.detectIntentStream(
PROJECT_ID, audioFilePath, SESSION_ID);

String output = bout.toString();

assertThat(output, CoreMatchers.containsString(
"Intent Display Name: room.reservation"));

assertThat(output, CoreMatchers.containsString(
"book"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ public class KnowledgeBaseManagementIT {

private static List<String> TEXTS = ImmutableList
.of("How do I sign up?", "Is my data redundant?", "Where can I find pricing information?",
"Where is my data stored?", "What are my support options?");
"Where is my data stored?", "What are my support options?",
"How can I maximize the availability of my data?");

@Before
public void setUp() {
Expand Down Expand Up @@ -167,11 +168,11 @@ public void testDetectIntentKnowledge() throws Exception {
for (String text : TEXTS) {
KnowledgeAnswers knowledgeAnswers = allAnswers.get(text);
if (knowledgeAnswers.getAnswersCount() > 0) {
answersFound++;
Answer answer = knowledgeAnswers.getAnswers(0);
assertEquals(text, answer.getFaqQuestion());
assertEquals(document.getName(), answer.getSource());
assertThat(answer.getAnswer()).contains("Cloud Storage");
if (text.equals(answer.getFaqQuestion()) && document.getName().equals(answer.getSource())
&& answer.getAnswer().contains("Cloud Storage")) {
answersFound++;
}
}
}
// To make the test less flaky, check that half of the texts got a result.
Expand Down

0 comments on commit da73918

Please sign in to comment.