Skip to content

Commit ac7294b

Browse files
committed
[AI] Add support for Thinking Levels
Gemini 2.5 series models and newer utilize a thinking process before generating a response. Thinking levels are an alternative to thinking budgets as they are preset values that Gemini 3 models can use to limit how many tokens are dedicated to the thinking process. The [thinking documentation](https://firebase.google.com/docs/ai-logic/thinking) gives more details.
1 parent f9495bc commit ac7294b

File tree

2 files changed

+76
-7
lines changed

2 files changed

+76
-7
lines changed

firebase-ai/src/main/kotlin/com/google/firebase/ai/type/ThinkingConfig.kt

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,17 @@ package com.google.firebase.ai.type
1919
import kotlinx.serialization.SerialName
2020
import kotlinx.serialization.Serializable
2121

22-
/** Configuration parameters for thinking features. */
22+
/**
23+
* Gemini 2.5 series models and newer utilize a thinking process before generating a response. This
24+
* allows them to reason through complex problems and plan a more coherent and accurate answer. See
25+
* the [thinking documentation](https://firebase.google.com/docs/ai-logic/thinking) for more
26+
* details.
27+
*/
2328
public class ThinkingConfig
2429
private constructor(
2530
internal val thinkingBudget: Int? = null,
26-
internal val includeThoughts: Boolean? = null
31+
internal val includeThoughts: Boolean? = null,
32+
internal val thinkingLevel: ThinkingLevel? = null
2733
) {
2834

2935
public class Builder() {
@@ -35,11 +41,19 @@ private constructor(
3541
@set:JvmSynthetic // hide void setter from Java
3642
public var includeThoughts: Boolean? = null
3743

44+
@JvmField
45+
@set:JvmSynthetic // hide void setter from Java
46+
public var thinkingLevel: ThinkingLevel? = null
47+
3848
/**
39-
* Indicates the thinking budget in tokens. `0` is disabled. `-1` is dynamic. The default values
40-
* and allowed ranges are model dependent.
49+
* Indicates the thinking budget in tokens.
50+
*
51+
* Use `0` for disabled, and `-1` for dynamic. The range of
52+
* [supported thinking budget values](https://firebase.google.com/docs/ai-logic/thinking#supported-thinking-budget-values)
53+
* depends on the model.
4154
*/
4255
public fun setThinkingBudget(thinkingBudget: Int): Builder = apply {
56+
assert(thinkingLevel == null) { "Cannot set both `thinkingBudget` and `thinkingLevel`" }
4357
this.thinkingBudget = thinkingBudget
4458
}
4559

@@ -55,16 +69,27 @@ private constructor(
5569
this.includeThoughts = includeThoughts
5670
}
5771

72+
/** Indicates the thinking budget based in Levels. */
73+
public fun setThinkingLevel(thinkingLevel: ThinkingLevel): Builder = apply {
74+
assert(thinkingBudget == null) { "Cannot set both `thinkingBudget` and `thinkingLevel`" }
75+
this.thinkingLevel = thinkingLevel
76+
}
77+
5878
public fun build(): ThinkingConfig =
59-
ThinkingConfig(thinkingBudget = thinkingBudget, includeThoughts = includeThoughts)
79+
ThinkingConfig(
80+
thinkingBudget = thinkingBudget,
81+
includeThoughts = includeThoughts,
82+
thinkingLevel = thinkingLevel
83+
)
6084
}
6185

62-
internal fun toInternal() = Internal(thinkingBudget, includeThoughts)
86+
internal fun toInternal() = Internal(thinkingBudget, includeThoughts, thinkingLevel?.toInternal())
6387

6488
@Serializable
6589
internal data class Internal(
6690
@SerialName("thinking_budget") val thinkingBudget: Int? = null,
67-
val includeThoughts: Boolean? = null
91+
val includeThoughts: Boolean? = null,
92+
@SerialName("thinking_level") val thinkingLevel: ThinkingLevel.Internal? = null,
6893
)
6994
}
7095

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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 com.google.firebase.ai.type
18+
19+
import kotlinx.serialization.SerialName
20+
import kotlinx.serialization.Serializable
21+
22+
/** Specifies the quality of the thinking response. */
23+
public class ThinkingLevel private constructor(public val ordinal: Int) {
24+
internal fun toInternal() =
25+
when (this) {
26+
LOW -> Internal.LOW
27+
HIGH -> Internal.HIGH
28+
else -> throw makeMissingCaseException("ThinkingLevel", ordinal)
29+
}
30+
31+
@Serializable
32+
internal enum class Internal {
33+
@SerialName("THINKING_LEVEL_UNSPECIFIED") UNSPECIFIED,
34+
LOW,
35+
HIGH,
36+
}
37+
public companion object {
38+
/** A lower quality thinking response, which provides low latency. */
39+
@JvmField public val LOW: ThinkingLevel = ThinkingLevel(0)
40+
41+
/** A higher quality thinking response, which may increase latency. */
42+
@JvmField public val HIGH: ThinkingLevel = ThinkingLevel(1)
43+
}
44+
}

0 commit comments

Comments
 (0)