Skip to content

Commit d0943c0

Browse files
jdomingrJuan Dominguez
andauthored
feat(genai): add live samples (1) (#10194)
* feat(genai): add live samples(1) * refactor(genai): change way of handling live server messages * chore(genai): update genai version * refactor(genai): change return type and improve comments --------- Co-authored-by: Juan Dominguez <[email protected]>
1 parent 23c44ea commit d0943c0

File tree

6 files changed

+559
-5
lines changed

6 files changed

+559
-5
lines changed

genai/snippets/pom.xml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,13 @@
5151
<dependency>
5252
<groupId>com.google.genai</groupId>
5353
<artifactId>google-genai</artifactId>
54-
<version>1.23.0</version>
54+
<version>1.28.0</version>
5555
</dependency>
5656
<dependency>
5757
<groupId>com.google.cloud</groupId>
5858
<artifactId>google-cloud-storage</artifactId>
5959
<scope>test</scope>
6060
</dependency>
61-
<dependency>
62-
<groupId>com.google.cloud</groupId>
63-
<artifactId>google-cloud-storage</artifactId>
64-
</dependency>
6561
<dependency>
6662
<artifactId>junit</artifactId>
6763
<groupId>junit</groupId>
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package genai.live;
18+
19+
// [START googlegenaisdk_live_code_exec_with_txt]
20+
21+
import static com.google.genai.types.Modality.Known.TEXT;
22+
23+
import com.google.genai.AsyncSession;
24+
import com.google.genai.Client;
25+
import com.google.genai.types.Content;
26+
import com.google.genai.types.LiveConnectConfig;
27+
import com.google.genai.types.LiveSendClientContentParameters;
28+
import com.google.genai.types.LiveServerContent;
29+
import com.google.genai.types.LiveServerMessage;
30+
import com.google.genai.types.Part;
31+
import com.google.genai.types.Tool;
32+
import com.google.genai.types.ToolCodeExecution;
33+
import java.util.concurrent.CompletableFuture;
34+
35+
public class LiveCodeExecWithTxt {
36+
37+
public static void main(String[] args) {
38+
// TODO(developer): Replace these variables before running the sample.
39+
String modelId = "gemini-2.0-flash-live-preview-04-09";
40+
generateContent(modelId);
41+
}
42+
43+
// Shows how to generate content with the Code Execution tool and a text input.
44+
public static String generateContent(String modelId) {
45+
// Client Initialization. Once created, it can be reused for multiple requests.
46+
try (Client client = Client.builder().location("us-central1").vertexAI(true).build()) {
47+
48+
// Connects to the live server.
49+
CompletableFuture<AsyncSession> sessionFuture =
50+
client.async.live.connect(
51+
modelId,
52+
LiveConnectConfig.builder()
53+
.responseModalities(TEXT)
54+
.tools(Tool.builder().codeExecution(ToolCodeExecution.builder().build()).build())
55+
.build());
56+
57+
// Sends and receives messages from the live session.
58+
CompletableFuture<String> responseFuture =
59+
sessionFuture.thenCompose(
60+
session -> {
61+
// A future that completes when the model signals the end of its turn.
62+
CompletableFuture<Void> turnComplete = new CompletableFuture<>();
63+
// A variable to concatenate the text response from the model.
64+
StringBuilder modelResponse = new StringBuilder();
65+
// Starts receiving messages from the live session.
66+
session.receive(
67+
message -> handleLiveServerMessage(message, turnComplete, modelResponse));
68+
// Sends content to the live session and waits for the turn to complete.
69+
return sendContent(session)
70+
.thenCompose(unused -> turnComplete)
71+
.thenCompose(
72+
unused -> session.close().thenApply(result -> modelResponse.toString()));
73+
});
74+
75+
String response = responseFuture.join();
76+
System.out.println(response);
77+
// Example output:
78+
// > Compute the largest prime palindrome under 100000
79+
//
80+
// Okay, I understand. I need to find the largest prime number that is also a palindrome
81+
// and is less than 100000. Here's my plan...
82+
return response;
83+
}
84+
}
85+
86+
// Sends content to the live session.
87+
private static CompletableFuture<Void> sendContent(AsyncSession session) {
88+
String textInput = "Compute the largest prime palindrome under 100000";
89+
System.out.printf("> %s\n", textInput);
90+
return session.sendClientContent(
91+
LiveSendClientContentParameters.builder()
92+
.turns(Content.builder().role("user").parts(Part.fromText(textInput)).build())
93+
.turnComplete(true)
94+
.build());
95+
}
96+
97+
// Concatenates the response messages from the model and signals
98+
// `turnComplete` when the model is done generating the response.
99+
private static void handleLiveServerMessage(
100+
LiveServerMessage message, CompletableFuture<Void> turnComplete, StringBuilder response) {
101+
message
102+
.serverContent()
103+
.flatMap(LiveServerContent::modelTurn)
104+
.flatMap(Content::parts)
105+
.ifPresent(
106+
parts ->
107+
parts.forEach(
108+
part -> {
109+
part.text().ifPresent(response::append);
110+
part.executableCode().ifPresent(code -> System.out.println("code: " + code));
111+
part.codeExecutionResult()
112+
.ifPresent(result -> System.out.println("result: " + result));
113+
}));
114+
// Checks if the model's turn is over.
115+
if (message.serverContent().flatMap(LiveServerContent::turnComplete).orElse(false)) {
116+
turnComplete.complete(null);
117+
}
118+
}
119+
}
120+
// [END googlegenaisdk_live_code_exec_with_txt]
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package genai.live;
18+
19+
// [START googlegenaisdk_live_ground_googsearch_with_txt]
20+
21+
import static com.google.genai.types.Modality.Known.TEXT;
22+
23+
import com.google.genai.AsyncSession;
24+
import com.google.genai.Client;
25+
import com.google.genai.types.Content;
26+
import com.google.genai.types.GoogleSearch;
27+
import com.google.genai.types.LiveConnectConfig;
28+
import com.google.genai.types.LiveSendClientContentParameters;
29+
import com.google.genai.types.LiveServerContent;
30+
import com.google.genai.types.LiveServerMessage;
31+
import com.google.genai.types.Part;
32+
import com.google.genai.types.Tool;
33+
import java.util.concurrent.CompletableFuture;
34+
35+
public class LiveGroundGoogSearchWithTxt {
36+
37+
public static void main(String[] args) {
38+
// TODO(developer): Replace these variables before running the sample.
39+
String modelId = "gemini-2.0-flash-live-preview-04-09";
40+
generateContent(modelId);
41+
}
42+
43+
// Shows how to generate content with the Google Search tool and a text input.
44+
public static String generateContent(String modelId) {
45+
// Client Initialization. Once created, it can be reused for multiple requests.
46+
try (Client client = Client.builder().location("us-central1").vertexAI(true).build()) {
47+
48+
// Connects to the live server.
49+
CompletableFuture<AsyncSession> sessionFuture =
50+
client.async.live.connect(
51+
modelId,
52+
LiveConnectConfig.builder()
53+
.responseModalities(TEXT)
54+
.tools(Tool.builder().googleSearch(GoogleSearch.builder().build()).build())
55+
.build());
56+
57+
// Sends and receives messages from the live session.
58+
CompletableFuture<String> responseFuture =
59+
sessionFuture.thenCompose(
60+
session -> {
61+
// A future that completes when the model signals the end of its turn.
62+
CompletableFuture<Void> turnComplete = new CompletableFuture<>();
63+
// A variable to concatenate the text response from the model.
64+
StringBuilder modelResponse = new StringBuilder();
65+
// Starts receiving messages from the live session.
66+
session.receive(
67+
message -> handleLiveServerMessage(message, turnComplete, modelResponse));
68+
// Sends content to the live session and waits for the turn to complete.
69+
return sendContent(session)
70+
.thenCompose(unused -> turnComplete)
71+
.thenCompose(
72+
unused -> session.close().thenApply(result -> modelResponse.toString()));
73+
});
74+
75+
String response = responseFuture.join();
76+
System.out.println(response);
77+
// Example output:
78+
// > When did the last Brazil vs. Argentina soccer match happen?
79+
//
80+
// The most recent Brazil vs. Argentina soccer match was on March 25, 2025,
81+
// as part of the 2026 World Cup qualifiers. Argentina won 4-1.
82+
return response;
83+
}
84+
}
85+
86+
// Sends content to the live session.
87+
private static CompletableFuture<Void> sendContent(AsyncSession session) {
88+
String textInput = "When did the last Brazil vs. Argentina soccer match happen?";
89+
System.out.printf("> %s\n", textInput);
90+
return session.sendClientContent(
91+
LiveSendClientContentParameters.builder()
92+
.turns(Content.builder().role("user").parts(Part.fromText(textInput)).build())
93+
.turnComplete(true)
94+
.build());
95+
}
96+
97+
// Concatenates the response messages from the model and signals
98+
// `turnComplete` when the model is done generating the response.
99+
private static void handleLiveServerMessage(
100+
LiveServerMessage message, CompletableFuture<Void> turnComplete, StringBuilder response) {
101+
message
102+
.serverContent()
103+
.flatMap(LiveServerContent::modelTurn)
104+
.flatMap(Content::parts)
105+
.ifPresent(parts -> parts.forEach(part -> part.text().ifPresent(response::append)));
106+
// Checks if the model's turn is over.
107+
if (message.serverContent().flatMap(LiveServerContent::turnComplete).orElse(false)) {
108+
turnComplete.complete(null);
109+
}
110+
}
111+
}
112+
// [END googlegenaisdk_live_ground_googsearch_with_txt]
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package genai.live;
18+
19+
// [START googlegenaisdk_live_transcribe_with_audio]
20+
21+
import static com.google.genai.types.Modality.Known.AUDIO;
22+
23+
import com.google.genai.AsyncSession;
24+
import com.google.genai.Client;
25+
import com.google.genai.types.AudioTranscriptionConfig;
26+
import com.google.genai.types.Content;
27+
import com.google.genai.types.LiveConnectConfig;
28+
import com.google.genai.types.LiveSendClientContentParameters;
29+
import com.google.genai.types.LiveServerContent;
30+
import com.google.genai.types.LiveServerMessage;
31+
import com.google.genai.types.Part;
32+
import com.google.genai.types.Transcription;
33+
import java.util.concurrent.CompletableFuture;
34+
35+
public class LiveTranscribeWithAudio {
36+
37+
public static void main(String[] args) {
38+
// TODO(developer): Replace these variables before running the sample.
39+
String modelId = "gemini-live-2.5-flash-preview-native-audio";
40+
generateContent(modelId);
41+
}
42+
43+
// Shows how to transcribe audio.
44+
public static String generateContent(String modelId) {
45+
// Client Initialization. Once created, it can be reused for multiple requests.
46+
try (Client client = Client.builder().location("us-central1").vertexAI(true).build()) {
47+
48+
// Connects to the live server.
49+
CompletableFuture<AsyncSession> sessionFuture =
50+
client.async.live.connect(
51+
modelId,
52+
LiveConnectConfig.builder()
53+
.responseModalities(AUDIO)
54+
.inputAudioTranscription(AudioTranscriptionConfig.builder().build())
55+
.outputAudioTranscription(AudioTranscriptionConfig.builder().build())
56+
.build());
57+
58+
// Sends and receives messages from the live session.
59+
CompletableFuture<String> responseFuture =
60+
sessionFuture.thenCompose(
61+
session -> {
62+
// A future that completes when the model signals the end of its turn.
63+
CompletableFuture<Void> turnComplete = new CompletableFuture<>();
64+
// A variable to concatenate the text response from the model.
65+
StringBuilder modelResponse = new StringBuilder();
66+
// Starts receiving messages from the live session.
67+
session.receive(
68+
message -> handleLiveServerMessage(message, turnComplete, modelResponse));
69+
// Sends content to the live session and waits for the turn to complete.
70+
return sendContent(session)
71+
.thenCompose(unused -> turnComplete)
72+
.thenCompose(
73+
unused -> session.close().thenApply(result -> modelResponse.toString()));
74+
});
75+
76+
String response = responseFuture.join();
77+
System.out.println(response);
78+
// Example output:
79+
// > Hello? Gemini, are you there?
80+
//
81+
// Yes, I'm here. How can I help you today?
82+
return response;
83+
}
84+
}
85+
86+
// Sends content to the live session.
87+
private static CompletableFuture<Void> sendContent(AsyncSession session) {
88+
String textInput = "Hello? Gemini, are you there?";
89+
System.out.printf("> %s\n", textInput);
90+
return session.sendClientContent(
91+
LiveSendClientContentParameters.builder()
92+
.turns(Content.builder().role("user").parts(Part.fromText(textInput)).build())
93+
.turnComplete(true)
94+
.build());
95+
}
96+
97+
// Concatenates the output transcription from the model and signals
98+
// `turnComplete` when the model is done generating the response.
99+
private static void handleLiveServerMessage(
100+
LiveServerMessage message, CompletableFuture<Void> turnComplete, StringBuilder response) {
101+
102+
message
103+
.serverContent()
104+
.ifPresent(
105+
serverContent -> {
106+
serverContent
107+
.modelTurn()
108+
.ifPresent(modelTurn -> System.out.println("Model turn: " + modelTurn.parts()));
109+
110+
serverContent
111+
.inputTranscription()
112+
.flatMap(Transcription::text)
113+
.ifPresent(text -> System.out.println("Input transcript: " + text));
114+
115+
serverContent
116+
.outputTranscription()
117+
.flatMap(Transcription::text)
118+
.ifPresent(response::append);
119+
// Checks if the model's turn is over.
120+
if (serverContent.turnComplete().orElse(false)) {
121+
turnComplete.complete(null);
122+
}
123+
});
124+
}
125+
}
126+
// [END googlegenaisdk_live_transcribe_with_audio]

0 commit comments

Comments
 (0)