Skip to content

Commit 274a527

Browse files
jdomingrJuan Dominguez
andauthored
feat: add new GenAI SDK count tokens samples (#10145)
* remove unused imports * feat: add new GenAI count tokens samples * feat: add new tests for count tokens samples * refactor: add new asserts to make sure CountTokensReponseWithText return data * refactor: update compute tokens to change logic that prints tokens info * fix controlled generation test case --------- Co-authored-by: Juan Dominguez <[email protected]>
1 parent 1659204 commit 274a527

File tree

4 files changed

+177
-4
lines changed

4 files changed

+177
-4
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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.counttokens;
18+
19+
// [START googlegenaisdk_counttoken_compute_with_txt]
20+
21+
import com.google.genai.Client;
22+
import com.google.genai.types.ComputeTokensResponse;
23+
import com.google.genai.types.HttpOptions;
24+
import com.google.genai.types.TokensInfo;
25+
import java.nio.charset.StandardCharsets;
26+
import java.util.List;
27+
import java.util.Optional;
28+
29+
public class CountTokensComputeWithText {
30+
31+
public static void main(String[] args) {
32+
// TODO(developer): Replace these variables before running the sample.
33+
String modelId = "gemini-2.5-flash";
34+
computeTokens(modelId);
35+
}
36+
37+
// Computes tokens with text input
38+
public static Optional<List<TokensInfo>> computeTokens(String modelId) {
39+
// Initialize client that will be used to send requests. This client only needs to be created
40+
// once, and can be reused for multiple requests.
41+
try (Client client =
42+
Client.builder()
43+
.location("global")
44+
.vertexAI(true)
45+
.httpOptions(HttpOptions.builder().apiVersion("v1").build())
46+
.build()) {
47+
48+
ComputeTokensResponse response = client.models.computeTokens(
49+
modelId, "What's the longest word in the English language?", null);
50+
51+
// Print TokensInfo
52+
response.tokensInfo().ifPresent(tokensInfoList -> {
53+
for (TokensInfo info : tokensInfoList) {
54+
info.role().ifPresent(role -> System.out.println("role: " + role));
55+
info.tokenIds().ifPresent(tokenIds -> System.out.println("tokenIds: " + tokenIds));
56+
// print tokens input as strings since they are in a form of byte array
57+
System.out.println("tokens: ");
58+
info.tokens().ifPresent(tokens ->
59+
tokens.forEach(token ->
60+
System.out.println(new String(token, StandardCharsets.UTF_8))
61+
)
62+
);
63+
}
64+
});
65+
// Example response.tokensInfo()
66+
// role: user
67+
// tokenIds: [1841, 235303, 235256, 573, 32514, 2204, 575, 573, 4645, 5255, 235336]
68+
// tokens:
69+
// What
70+
// '
71+
// s
72+
// the
73+
return response.tokensInfo();
74+
}
75+
}
76+
}
77+
// [END googlegenaisdk_counttoken_compute_with_txt]
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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.counttokens;
18+
19+
// [START googlegenaisdk_counttoken_resp_with_txt]
20+
21+
import com.google.genai.Client;
22+
import com.google.genai.types.GenerateContentResponse;
23+
import com.google.genai.types.GenerateContentResponseUsageMetadata;
24+
import com.google.genai.types.HttpOptions;
25+
import java.util.Optional;
26+
27+
public class CountTokensResponseWithText {
28+
29+
public static void main(String[] args) {
30+
// TODO(developer): Replace these variables before running the sample.
31+
String modelId = "gemini-2.5-flash";
32+
countTokens(modelId);
33+
}
34+
35+
// Generates content response usage metadata that contains prompt and response token counts
36+
public static Optional<GenerateContentResponseUsageMetadata> countTokens(String modelId) {
37+
// Initialize client that will be used to send requests. This client only needs to be created
38+
// once, and can be reused for multiple requests.
39+
try (Client client =
40+
Client.builder()
41+
.location("global")
42+
.vertexAI(true)
43+
.httpOptions(HttpOptions.builder().apiVersion("v1").build())
44+
.build()) {
45+
46+
GenerateContentResponse response =
47+
client.models.generateContent(modelId, "Why is the sky blue?", null);
48+
49+
response.usageMetadata().ifPresent(System.out::println);
50+
// Example response:
51+
// GenerateContentResponseUsageMetadata{cacheTokensDetails=Optional.empty,
52+
// cachedContentTokenCount=Optional.empty, candidatesTokenCount=Optional[569],
53+
// candidatesTokensDetails=Optional[[ModalityTokenCount{modality=Optional[TEXT],
54+
// tokenCount=Optional[569]}]], promptTokenCount=Optional[6],
55+
// promptTokensDetails=Optional[[ModalityTokenCount{modality=Optional[TEXT],
56+
// tokenCount=Optional[6]}]], thoughtsTokenCount=Optional[1132],
57+
// toolUsePromptTokenCount=Optional.empty, toolUsePromptTokensDetails=Optional.empty,
58+
// totalTokenCount=Optional[1707], trafficType=Optional[ON_DEMAND]}
59+
return response.usageMetadata();
60+
}
61+
}
62+
}
63+
// [END googlegenaisdk_counttoken_resp_with_txt]

genai/snippets/src/main/java/genai/counttokens/CountTokensWithText.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,8 @@
1919
// [START googlegenaisdk_counttoken_with_txt]
2020

2121
import com.google.genai.Client;
22-
import com.google.genai.types.Content;
2322
import com.google.genai.types.CountTokensResponse;
2423
import com.google.genai.types.HttpOptions;
25-
import com.google.genai.types.Part;
26-
import java.util.List;
2724
import java.util.Optional;
2825

2926
public class CountTokensWithText {

genai/snippets/src/test/java/genai/counttokens/CountTokensIT.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,12 @@
1919
import static com.google.common.truth.Truth.assertThat;
2020
import static com.google.common.truth.Truth.assertWithMessage;
2121

22+
import com.google.genai.types.GenerateContentResponseUsageMetadata;
23+
import com.google.genai.types.TokensInfo;
2224
import java.io.ByteArrayOutputStream;
2325
import java.io.PrintStream;
26+
import java.util.ArrayList;
27+
import java.util.List;
2428
import java.util.Optional;
2529
import org.junit.After;
2630
import org.junit.Before;
@@ -32,7 +36,6 @@
3236
@RunWith(JUnit4.class)
3337
public class CountTokensIT {
3438

35-
3639
private static final String GEMINI_FLASH = "gemini-2.5-flash";
3740
private ByteArrayOutputStream bout;
3841
private PrintStream out;
@@ -74,4 +77,37 @@ public void testCountTokensWithTextAndVideo() {
7477
assertThat(response).isPresent();
7578
assertThat(response.get()).isGreaterThan(6);
7679
}
80+
81+
@Test
82+
public void testCountTokensComputeWithText() {
83+
84+
List<TokensInfo> response =
85+
CountTokensComputeWithText.computeTokens(GEMINI_FLASH).orElse(new ArrayList<>());
86+
87+
assertThat(response).isNotEmpty();
88+
TokensInfo tokensInfo = response.get(0);
89+
90+
assertThat(tokensInfo.role()).isPresent();
91+
92+
assertThat(tokensInfo.tokenIds()).isPresent();
93+
assertThat(tokensInfo.tokenIds().get()).isNotEmpty();
94+
95+
assertThat(tokensInfo.tokens()).isPresent();
96+
assertThat(tokensInfo.tokens().get()).isNotEmpty();
97+
98+
}
99+
100+
@Test
101+
public void testCountTokensResponseWithText() {
102+
103+
Optional<GenerateContentResponseUsageMetadata> response =
104+
CountTokensResponseWithText.countTokens(GEMINI_FLASH);
105+
106+
assertThat(response).isPresent();
107+
assertThat(response.get().totalTokenCount()).isPresent();
108+
assertThat(response.get().totalTokenCount().get()).isGreaterThan(0);
109+
assertThat(response.get().promptTokenCount()).isPresent();
110+
assertThat(response.get().promptTokenCount().get()).isGreaterThan(0);
111+
112+
}
77113
}

0 commit comments

Comments
 (0)