Skip to content

Commit 19c4482

Browse files
jdomingrJuan Dominguez
andauthored
feat(genai): add thinking samples (#10160)
* feat: add new genAI thinking with text sample * feat: add new GenAI sdk thinking with budget sample * feat: add new GenAI sdk thinking with thoughts sample * feat(genai): add test for ThinkingIncludeThoughts sample * refactor: change the way of getting the first candidate for an stream-based approach in Thinking with thoughts sample * refactor: change gemini model and change example responses * refactor: apply code review suggestions and change filenames to match with tags --------- Co-authored-by: Juan Dominguez <jdomin@softserveinc.com>
1 parent 9862b37 commit 19c4482

File tree

4 files changed

+382
-0
lines changed

4 files changed

+382
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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.thinking;
18+
19+
// [START googlegenaisdk_thinking_budget_with_txt]
20+
21+
import com.google.genai.Client;
22+
import com.google.genai.types.GenerateContentConfig;
23+
import com.google.genai.types.GenerateContentResponse;
24+
import com.google.genai.types.HttpOptions;
25+
import com.google.genai.types.ThinkingConfig;
26+
27+
public class ThinkingBudgetWithTxt {
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+
generateContent(modelId);
33+
}
34+
35+
// Generates text controlling the thinking budget
36+
public static String generateContent(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+
GenerateContentConfig contentConfig =
47+
GenerateContentConfig.builder()
48+
.thinkingConfig(ThinkingConfig.builder().thinkingBudget(1024).build())
49+
.build();
50+
51+
GenerateContentResponse response =
52+
client.models.generateContent(modelId, "solve x^2 + 4x + 4 = 0", contentConfig);
53+
54+
System.out.println(response.text());
55+
// Example response:
56+
// To solve the equation $x^2 + 4x + 4 = 0$, we can use several methods:
57+
//
58+
// **Method 1: Factoring (Recognizing a Perfect Square Trinomial)**
59+
//
60+
// Notice that the left side of the equation is a perfect square trinomial. It fits the form
61+
// $a^2 + 2ab + b^2 = (a+b)^2$...
62+
// ...
63+
// The solution is $x = -2$.
64+
65+
response
66+
.usageMetadata()
67+
.ifPresent(
68+
metadata -> {
69+
System.out.println("Token count for thinking: " + metadata.thoughtsTokenCount());
70+
System.out.println("Total token count: " + metadata.totalTokenCount());
71+
});
72+
// Example response:
73+
// Token count for thinking: Optional[885]
74+
// Total token count: Optional[1468]
75+
return response.text();
76+
}
77+
}
78+
}
79+
// [END googlegenaisdk_thinking_budget_with_txt]
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
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.thinking;
18+
19+
// [START googlegenaisdk_thinking_includethoughts_with_txt]
20+
21+
import com.google.genai.Client;
22+
import com.google.genai.types.Candidate;
23+
import com.google.genai.types.Content;
24+
import com.google.genai.types.GenerateContentConfig;
25+
import com.google.genai.types.GenerateContentResponse;
26+
import com.google.genai.types.HttpOptions;
27+
import com.google.genai.types.ThinkingConfig;
28+
29+
public class ThinkingIncludeThoughtsWithTxt {
30+
31+
public static void main(String[] args) {
32+
// TODO(developer): Replace these variables before running the sample.
33+
String modelId = "gemini-2.5-pro";
34+
generateContent(modelId);
35+
}
36+
37+
// Generates text including thoughts in the response
38+
public static String generateContent(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+
GenerateContentConfig contentConfig =
49+
GenerateContentConfig.builder()
50+
.thinkingConfig(ThinkingConfig.builder().includeThoughts(true).build())
51+
.build();
52+
53+
GenerateContentResponse response =
54+
client.models.generateContent(modelId, "solve x^2 + 4x + 4 = 0", contentConfig);
55+
56+
System.out.println(response.text());
57+
// Example response:
58+
// We can solve the equation x² + 4x + 4 = 0 using a couple of common methods.
59+
//
60+
// ### Method 1: Factoring (The Easiest Method for this Problem)
61+
// **Recognize the pattern:** The pattern for a perfect square trinomial
62+
// is a² + 2ab + b² = (a + b)².
63+
// ...
64+
// ### Final Answer:
65+
// The solution is **x = -2**.
66+
67+
// Get parts of the response and print thoughts
68+
response
69+
.candidates()
70+
.flatMap(candidates -> candidates.stream().findFirst())
71+
.flatMap(Candidate::content)
72+
.flatMap(Content::parts)
73+
.ifPresent(
74+
parts -> {
75+
parts.forEach(
76+
part -> {
77+
if (part.thought().orElse(false)) {
78+
part.text().ifPresent(System.out::println);
79+
}
80+
});
81+
});
82+
// Example response:
83+
// Alright, let's break down this quadratic equation, x² + 4x + 4 = 0. My initial thought is,
84+
// "classic quadratic." I'll need to find the values of 'x' that make this equation true. The
85+
// equation is in standard form, and since the coefficients are relatively small, I
86+
// immediately suspect that factoring might be the easiest route. It's worth checking.
87+
//
88+
// First, I assessed what I had. *a* is 1, *b* is 4, and *c* is 4. I consider my toolkit.
89+
// Factoring is the likely first choice, then I can use the quadratic formula as a backup,
90+
// because that ALWAYS works, and I could use graphing. However, for this, factoring seems the
91+
// cleanest approach.
92+
//
93+
// Okay, factoring. I need two numbers that multiply to *c* (which is 4) and add up to *b*
94+
// (also 4). I quickly run through the factor pairs of 4: (1, 4), (-1, -4), (2, 2), (-2, -2).
95+
// Aha! 2 and 2 fit the bill. They multiply to 4 *and* add up to 4. Therefore, I can rewrite
96+
// the equation as (x + 2)(x + 2) = 0. That simplifies to (x + 2)² = 0. Perfect square
97+
// trinomial – nice and tidy. Seeing that pattern from the outset can save a step or two. Now,
98+
// to solve for *x*: if (x + 2)² = 0, then x + 2 must equal 0. Therefore, x = -2. Done.
99+
//
100+
// But, for the sake of a full explanation, let's use the quadratic formula as a second
101+
// method. It's a reliable way to double-check the answer, plus it's good practice. I plug my
102+
// *a*, *b*, and *c* values into the formula: x = [-b ± √(b² - 4ac)] / (2a). That gives me x
103+
// = [-4 ± √(4² - 4 * 1 * 4)] / (2 * 1). Simplifying under the radical, I get x = [-4 ± √(16 -
104+
// 16)] / 2. So, x = [-4 ± √0] / 2. The square root of 0 is zero, which is very telling! When
105+
// the discriminant (b² - 4ac) is zero, you get one real solution, a repeated root. This means
106+
// x = -4 / 2, which simplifies to x = -2. Exactly the same as before.
107+
//
108+
// Therefore, the answer is x = -2. Factoring was the most straightforward route. For
109+
// completeness, I showed the solution via the quadratic formula, too. Both approaches lead to
110+
// the same single solution. This is a repeated root – a double root, if you will.
111+
//
112+
// And to be absolutely sure...let's check our answer! Substitute -2 back into the original
113+
// equation. (-2)² + 4(-2) + 4 = 4 - 8 + 4 = 0. Yep, 0 = 0. The solution is correct.
114+
return response.text();
115+
}
116+
}
117+
}
118+
// [END googlegenaisdk_thinking_includethoughts_with_txt]
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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.thinking;
18+
19+
// [START googlegenaisdk_thinking_with_txt]
20+
21+
import com.google.genai.Client;
22+
import com.google.genai.types.GenerateContentConfig;
23+
import com.google.genai.types.GenerateContentResponse;
24+
import com.google.genai.types.HttpOptions;
25+
26+
public class ThinkingWithTxt {
27+
28+
public static void main(String[] args) {
29+
// TODO(developer): Replace these variables before running the sample.
30+
String modelId = "gemini-2.5-pro";
31+
generateContent(modelId);
32+
}
33+
34+
// Generates text with thinking model and text input
35+
public static String generateContent(String modelId) {
36+
// Initialize client that will be used to send requests. This client only needs to be created
37+
// once, and can be reused for multiple requests.
38+
try (Client client =
39+
Client.builder()
40+
.location("global")
41+
.vertexAI(true)
42+
.httpOptions(HttpOptions.builder().apiVersion("v1").build())
43+
.build()) {
44+
45+
GenerateContentResponse response =
46+
client.models.generateContent(
47+
modelId, "solve x^2 + 4x + 4 = 0", GenerateContentConfig.builder().build());
48+
49+
System.out.println(response.text());
50+
// Example response:
51+
// There are a couple of common ways to solve this quadratic equation.
52+
//
53+
// The equation is: **x² + 4x + 4 = 0**
54+
//
55+
// ### Method 1: Factoring (The Easiest Method for this Problem)
56+
//
57+
// This equation is a special case called a "perfect square trinomial".
58+
//
59+
// 1. **Find two numbers** that multiply to the last term (4) and add up to the middle term
60+
// (4).
61+
// * The numbers are +2 and +2. (Since 2 * 2 = 4 and 2 + 2 = 4)
62+
//
63+
// 2. **Factor the equation** using these numbers.
64+
// * (x + 2)(x + 2) = 0
65+
// * This can be written as: (x + 2)² = 0
66+
//
67+
// 3. **Solve for x.**
68+
// * If (x + 2)² is zero, then (x + 2) must be zero.
69+
// * x + 2 = 0
70+
// * x = -2
71+
//
72+
// ### Method 2: The Quadratic Formula
73+
//
74+
// You can use the quadratic formula for any equation in the form ax² + bx + c = 0.
75+
//
76+
// The formula is: **x = [-b ± √(b² - 4ac)] / 2a**
77+
//
78+
// 1. **Identify a, b, and c** from your equation (x² + 4x + 4 = 0).
79+
// * a = 1
80+
// * b = 4
81+
// * c = 4
82+
//
83+
// 2. **Plug the values into the formula.**
84+
// * x = [-4 ± √(4² - 4 * 1 * 4)] / (2 * 1)
85+
//
86+
// 3. **Simplify.**
87+
// * x = [-4 ± √(16 - 16)] / 2
88+
// * x = [-4 ± √0] / 2
89+
// * x = -4 / 2
90+
// * x = -2
91+
//
92+
// Both methods give the same solution.
93+
//
94+
// ---
95+
//
96+
// ### Final Answer
97+
//
98+
// The solution is **x = -2**.
99+
return response.text();
100+
}
101+
}
102+
}
103+
// [END googlegenaisdk_thinking_with_txt]
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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.thinking;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
import static com.google.common.truth.Truth.assertWithMessage;
21+
22+
import java.io.ByteArrayOutputStream;
23+
import java.io.PrintStream;
24+
import org.junit.After;
25+
import org.junit.Before;
26+
import org.junit.BeforeClass;
27+
import org.junit.Test;
28+
import org.junit.runner.RunWith;
29+
import org.junit.runners.JUnit4;
30+
31+
@RunWith(JUnit4.class)
32+
public class ThinkingIT {
33+
34+
private static final String GEMINI_FLASH = "gemini-2.5-flash";
35+
private ByteArrayOutputStream bout;
36+
private PrintStream out;
37+
38+
// Check if the required environment variables are set.
39+
public static void requireEnvVar(String envVarName) {
40+
assertWithMessage(String.format("Missing environment variable '%s' ", envVarName))
41+
.that(System.getenv(envVarName))
42+
.isNotEmpty();
43+
}
44+
45+
@BeforeClass
46+
public static void checkRequirements() {
47+
requireEnvVar("GOOGLE_CLOUD_PROJECT");
48+
}
49+
50+
@Before
51+
public void setUp() {
52+
bout = new ByteArrayOutputStream();
53+
out = new PrintStream(bout);
54+
System.setOut(out);
55+
}
56+
57+
@After
58+
public void tearDown() {
59+
System.setOut(null);
60+
bout.reset();
61+
}
62+
63+
@Test
64+
public void testThinkingWithText() {
65+
String response = ThinkingWithTxt.generateContent(GEMINI_FLASH);
66+
assertThat(response).isNotEmpty();
67+
}
68+
69+
@Test
70+
public void testThinkingBudgetWithText() {
71+
String response = ThinkingBudgetWithTxt.generateContent(GEMINI_FLASH);
72+
assertThat(response).isNotEmpty();
73+
assertThat(bout.toString()).contains("Token count for thinking: ");
74+
assertThat(bout.toString()).contains("Total token count: ");
75+
}
76+
77+
@Test
78+
public void testThinkingIncludeThoughtsWithText() {
79+
String response = ThinkingIncludeThoughtsWithTxt.generateContent(GEMINI_FLASH);
80+
assertThat(response).isNotEmpty();
81+
}
82+
}

0 commit comments

Comments
 (0)