From 2652c678150e2b7b7ac386c407fb3df3bdcbc6a1 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Fri, 12 Dec 2025 11:35:20 -0800 Subject: [PATCH 1/4] Add thinking levels. --- packages/ai/src/types/enums.ts | 23 +++++++++++++++++++++++ packages/ai/src/types/requests.ts | 22 +++++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/packages/ai/src/types/enums.ts b/packages/ai/src/types/enums.ts index f7c55d5e4c..90aa5e5060 100644 --- a/packages/ai/src/types/enums.ts +++ b/packages/ai/src/types/enums.ts @@ -432,3 +432,26 @@ export const Language = { * @beta */ export type Language = (typeof Language)[keyof typeof Language]; + +/** + * A preset that controls the model's "thinking" process. Use + * `ThinkingLevel.LOW` for faster responses on less complex tasks, and + * `ThinkingLevel.HIGH` for better reasoning on more complex tasks. + * + * @public + */ +export const ThinkingLevel = { + MINIMAL: 'MINIMAL', + LOW: 'LOW', + MEDIUM: 'MEDIUM', + HIGH: 'HIGH' +}; + +/** + * A preset that controls the model's "thinking" process. Use + * `ThinkingLevel.LOW` for faster responses on less complex tasks, and + * `ThinkingLevel.HIGH` for better reasoning on more complex tasks. + * + * @public + */ +export type ThinkingLevel = (typeof ThinkingLevel)[keyof typeof ThinkingLevel]; diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index 6e5d214768..4389c2859d 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -27,7 +27,8 @@ import { HarmBlockThreshold, HarmCategory, InferenceMode, - ResponseModality + ResponseModality, + ThinkingLevel } from './enums'; import { ObjectSchemaRequest, SchemaRequest } from './schema'; @@ -440,14 +441,29 @@ export interface ThinkingConfig { * "thinking" process. A higher budget may result in higher quality responses for complex tasks * but can also increase latency and cost. * - * If you don't specify a budget, the model will determine the appropriate amount - * of thinking based on the complexity of the prompt. + * The range of supported thinking budget values depends on the model. + * + * - To use the default thinking budget or thinking level for a model, leave + * this value undefined. + * + * - To disable thinking, when supported by the model, set this value to `0`. + * + * - To use dynamic thinking, allowing the model to decide on the thinking + * budget based on the task, set this value to `-1`. * * An error will be thrown if you set a thinking budget for a model that does not support this * feature or if the specified budget is not within the model's supported range. */ thinkingBudget?: number; + /** + * If not specified, Gemini will use the model's default dynamic thinking level. + * + * Important: Gemini 2.5 series models do not support thinking levels; use + * `thinkingBudget` to set a thinking budget instead. + */ + thinkingLevel?: ThinkingLevel; + /** * Whether to include "thought summaries" in the model's response. * From 48211fa692e49fe3235d9113eca64899c207e3ba Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Fri, 12 Dec 2025 13:06:02 -0800 Subject: [PATCH 2/4] Tests, docs, error --- .changeset/plenty-bulldogs-complain.md | 5 ++++ common/api-review/ai.api.md | 12 ++++++++ docs-devsite/ai.md | 27 +++++++++++++++++ docs-devsite/ai.thinkingconfig.md | 27 +++++++++++++++-- .../ai/src/models/generative-model.test.ts | 17 ++++++++++- packages/ai/src/models/generative-model.ts | 21 +++++++++++++- packages/ai/src/types/enums.ts | 4 +-- packages/ai/src/types/requests.ts | 29 +++++++++++++------ 8 files changed, 127 insertions(+), 15 deletions(-) create mode 100644 .changeset/plenty-bulldogs-complain.md diff --git a/.changeset/plenty-bulldogs-complain.md b/.changeset/plenty-bulldogs-complain.md new file mode 100644 index 0000000000..94f211b2a2 --- /dev/null +++ b/.changeset/plenty-bulldogs-complain.md @@ -0,0 +1,5 @@ +--- +'@firebase/ai': minor +--- + +Added ability to specify thinking levels in `thinkingConfig`. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 2bf194fbaf..4d28570404 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -1371,8 +1371,20 @@ export interface TextPart { export interface ThinkingConfig { includeThoughts?: boolean; thinkingBudget?: number; + thinkingLevel?: ThinkingLevel; } +// @public +export const ThinkingLevel: { + MINIMAL: string; + LOW: string; + MEDIUM: string; + HIGH: string; +}; + +// @public +export type ThinkingLevel = (typeof ThinkingLevel)[keyof typeof ThinkingLevel]; + // Warning: (ae-incompatible-release-tags) The symbol "Tool" is marked as @public, but its signature references "CodeExecutionTool" which is marked as @beta // Warning: (ae-incompatible-release-tags) The symbol "Tool" is marked as @public, but its signature references "URLContextTool" which is marked as @beta // diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index 53e4057cad..172f060f14 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -176,6 +176,7 @@ The Firebase AI Web SDK. | [POSSIBLE\_ROLES](./ai.md#possible_roles) | Possible roles. | | [ResponseModality](./ai.md#responsemodality) | (Public Preview) Generation modalities to be returned in generation responses. | | [SchemaType](./ai.md#schematype) | Contains the list of OpenAPI data types as defined by the [OpenAPI specification](https://swagger.io/docs/specification/data-models/data-types/) | +| [ThinkingLevel](./ai.md#thinkinglevel) | A preset that controls the model's "thinking" process. Use ThinkingLevel.LOW for faster responses on less complex tasks, and ThinkingLevel.HIGH for better reasoning on more complex tasks. | | [URLRetrievalStatus](./ai.md#urlretrievalstatus) | (Public Preview) The status of a URL retrieval. | ## Type Aliases @@ -208,6 +209,7 @@ The Firebase AI Web SDK. | [ResponseModality](./ai.md#responsemodality) | (Public Preview) Generation modalities to be returned in generation responses. | | [Role](./ai.md#role) | Role is the producer of the content. | | [SchemaType](./ai.md#schematype) | Contains the list of OpenAPI data types as defined by the [OpenAPI specification](https://swagger.io/docs/specification/data-models/data-types/) | +| [ThinkingLevel](./ai.md#thinkinglevel) | A preset that controls the model's "thinking" process. Use ThinkingLevel.LOW for faster responses on less complex tasks, and ThinkingLevel.HIGH for better reasoning on more complex tasks. | | [Tool](./ai.md#tool) | Defines a tool that model can call to access external knowledge. | | [TypedSchema](./ai.md#typedschema) | A type that includes all specific Schema types. | | [URLRetrievalStatus](./ai.md#urlretrievalstatus) | (Public Preview) The status of a URL retrieval. | @@ -827,6 +829,21 @@ SchemaType: { } ``` +## ThinkingLevel + +A preset that controls the model's "thinking" process. Use `ThinkingLevel.LOW` for faster responses on less complex tasks, and `ThinkingLevel.HIGH` for better reasoning on more complex tasks. + +Signature: + +```typescript +ThinkingLevel: { + MINIMAL: string; + LOW: string; + MEDIUM: string; + HIGH: string; +} +``` + ## URLRetrievalStatus > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1142,6 +1159,16 @@ Contains the list of OpenAPI data types as defined by the [OpenAPI specification export type SchemaType = (typeof SchemaType)[keyof typeof SchemaType]; ``` +## ThinkingLevel + +A preset that controls the model's "thinking" process. Use `ThinkingLevel.LOW` for faster responses on less complex tasks, and `ThinkingLevel.HIGH` for better reasoning on more complex tasks. + +Signature: + +```typescript +export type ThinkingLevel = (typeof ThinkingLevel)[keyof typeof ThinkingLevel]; +``` + ## Tool Defines a tool that model can call to access external knowledge. diff --git a/docs-devsite/ai.thinkingconfig.md b/docs-devsite/ai.thinkingconfig.md index 1ddc1626f4..118aa0d3e3 100644 --- a/docs-devsite/ai.thinkingconfig.md +++ b/docs-devsite/ai.thinkingconfig.md @@ -25,7 +25,8 @@ export interface ThinkingConfig | Property | Type | Description | | --- | --- | --- | | [includeThoughts](./ai.thinkingconfig.md#thinkingconfigincludethoughts) | boolean | Whether to include "thought summaries" in the model's response. | -| [thinkingBudget](./ai.thinkingconfig.md#thinkingconfigthinkingbudget) | number | The thinking budget, in tokens.This parameter sets an upper limit on the number of tokens the model can use for its internal "thinking" process. A higher budget may result in higher quality responses for complex tasks but can also increase latency and cost.If you don't specify a budget, the model will determine the appropriate amount of thinking based on the complexity of the prompt.An error will be thrown if you set a thinking budget for a model that does not support this feature or if the specified budget is not within the model's supported range. | +| [thinkingBudget](./ai.thinkingconfig.md#thinkingconfigthinkingbudget) | number | The thinking budget, in tokens. | +| [thinkingLevel](./ai.thinkingconfig.md#thinkingconfigthinkinglevel) | [ThinkingLevel](./ai.md#thinkinglevel) | If not specified, Gemini will use the model's default dynamic thinking level. | ## ThinkingConfig.includeThoughts @@ -45,12 +46,34 @@ The thinking budget, in tokens. This parameter sets an upper limit on the number of tokens the model can use for its internal "thinking" process. A higher budget may result in higher quality responses for complex tasks but can also increase latency and cost. -If you don't specify a budget, the model will determine the appropriate amount of thinking based on the complexity of the prompt. +The range of supported thinking budget values depends on the model. + + An error will be thrown if you set a thinking budget for a model that does not support this feature or if the specified budget is not within the model's supported range. +The model will also error if `thinkingLevel` and `thinkingBudget` are both set. + Signature: ```typescript thinkingBudget?: number; ``` + +## ThinkingConfig.thinkingLevel + +If not specified, Gemini will use the model's default dynamic thinking level. + +Note: The model will error if `thinkingLevel` and `thinkingBudget` are both set. + +Important: Gemini 2.5 series models do not support thinking levels; use `thinkingBudget` to set a thinking budget instead. + +Signature: + +```typescript +thinkingLevel?: ThinkingLevel; +``` diff --git a/packages/ai/src/models/generative-model.test.ts b/packages/ai/src/models/generative-model.test.ts index 45430cb5f5..794508e6e7 100644 --- a/packages/ai/src/models/generative-model.test.ts +++ b/packages/ai/src/models/generative-model.test.ts @@ -21,7 +21,8 @@ import { AI, InferenceMode, AIErrorCode, - ChromeAdapter + ChromeAdapter, + ThinkingLevel } from '../public-types'; import * as request from '../requests/request'; import { SinonStub, match, restore, stub } from 'sinon'; @@ -53,6 +54,20 @@ const fakeAI: AI = { }; describe('GenerativeModel', () => { + it('throws if generationConfig is invalid', () => { + expect( + () => + new GenerativeModel(fakeAI, { + model: 'my-model', + generationConfig: { + thinkingConfig: { + thinkingBudget: 1000, + thinkingLevel: ThinkingLevel.LOW + } + } + }) + ).to.throw(AIErrorCode.UNSUPPORTED); + }); it('passes params through to generateContent', async () => { const genModel = new GenerativeModel( fakeAI, diff --git a/packages/ai/src/models/generative-model.ts b/packages/ai/src/models/generative-model.ts index ffce645eeb..5e09be14d0 100644 --- a/packages/ai/src/models/generative-model.ts +++ b/packages/ai/src/models/generative-model.ts @@ -41,9 +41,10 @@ import { formatGenerateContentInput, formatSystemInstruction } from '../requests/request-helpers'; -import { AI } from '../public-types'; +import { AI, AIErrorCode } from '../public-types'; import { AIModel } from './ai-model'; import { ChromeAdapter } from '../types/chrome-adapter'; +import { AIError } from '../errors'; /** * Class for generative model APIs. @@ -65,6 +66,7 @@ export class GenerativeModel extends AIModel { ) { super(ai, modelParams.model); this.generationConfig = modelParams.generationConfig || {}; + validateGenerationConfig(this.generationConfig); this.safetySettings = modelParams.safetySettings || []; this.tools = modelParams.tools; this.toolConfig = modelParams.toolConfig; @@ -165,3 +167,20 @@ export class GenerativeModel extends AIModel { ); } } + +/** + * Client-side validation of some common `GenerationConfig` pitfalls, in order + * to save the developer a wasted request. + */ +function validateGenerationConfig(generationConfig: GenerationConfig): void { + if ( + // != allows for null and undefined. 0 is considered "set" by the model + generationConfig.thinkingConfig?.thinkingBudget != null && + generationConfig.thinkingConfig.thinkingLevel + ) { + throw new AIError( + AIErrorCode.UNSUPPORTED, + `Cannot set both thinkingBudget and thinkingLevel in a config.` + ); + } +} diff --git a/packages/ai/src/types/enums.ts b/packages/ai/src/types/enums.ts index 90aa5e5060..4e4a45805d 100644 --- a/packages/ai/src/types/enums.ts +++ b/packages/ai/src/types/enums.ts @@ -437,7 +437,7 @@ export type Language = (typeof Language)[keyof typeof Language]; * A preset that controls the model's "thinking" process. Use * `ThinkingLevel.LOW` for faster responses on less complex tasks, and * `ThinkingLevel.HIGH` for better reasoning on more complex tasks. - * + * * @public */ export const ThinkingLevel = { @@ -451,7 +451,7 @@ export const ThinkingLevel = { * A preset that controls the model's "thinking" process. Use * `ThinkingLevel.LOW` for faster responses on less complex tasks, and * `ThinkingLevel.HIGH` for better reasoning on more complex tasks. - * + * * @public */ export type ThinkingLevel = (typeof ThinkingLevel)[keyof typeof ThinkingLevel]; diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index 4389c2859d..f9b7818e5a 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -437,28 +437,39 @@ export interface ThinkingConfig { /** * The thinking budget, in tokens. * + * @remarks * This parameter sets an upper limit on the number of tokens the model can use for its internal * "thinking" process. A higher budget may result in higher quality responses for complex tasks * but can also increase latency and cost. * * The range of supported thinking budget values depends on the model. - * - * - To use the default thinking budget or thinking level for a model, leave - * this value undefined. - * - * - To disable thinking, when supported by the model, set this value to `0`. - * - * - To use dynamic thinking, allowing the model to decide on the thinking - * budget based on the task, set this value to `-1`. + * + * * * An error will be thrown if you set a thinking budget for a model that does not support this * feature or if the specified budget is not within the model's supported range. + * + * The model will also error if `thinkingLevel` and `thinkingBudget` are + * both set. */ thinkingBudget?: number; /** * If not specified, Gemini will use the model's default dynamic thinking level. - * + * + * @remarks + * Note: The model will error if `thinkingLevel` and `thinkingBudget` are + * both set. + * * Important: Gemini 2.5 series models do not support thinking levels; use * `thinkingBudget` to set a thinking budget instead. */ From 670d910435ae0ad7994a36199996de4267dc9698 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Fri, 12 Dec 2025 15:33:57 -0800 Subject: [PATCH 3/4] make config clearer --- packages/ai/src/models/generative-model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ai/src/models/generative-model.ts b/packages/ai/src/models/generative-model.ts index 5e09be14d0..959e21d9e2 100644 --- a/packages/ai/src/models/generative-model.ts +++ b/packages/ai/src/models/generative-model.ts @@ -176,7 +176,7 @@ function validateGenerationConfig(generationConfig: GenerationConfig): void { if ( // != allows for null and undefined. 0 is considered "set" by the model generationConfig.thinkingConfig?.thinkingBudget != null && - generationConfig.thinkingConfig.thinkingLevel + generationConfig.thinkingConfig?.thinkingLevel ) { throw new AIError( AIErrorCode.UNSUPPORTED, From 87464b75e146bbf2dfb51b0346dc18da0fa4ca76 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Fri, 12 Dec 2025 15:34:29 -0800 Subject: [PATCH 4/4] fix changeset --- .changeset/plenty-bulldogs-complain.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.changeset/plenty-bulldogs-complain.md b/.changeset/plenty-bulldogs-complain.md index 94f211b2a2..d8583106e6 100644 --- a/.changeset/plenty-bulldogs-complain.md +++ b/.changeset/plenty-bulldogs-complain.md @@ -1,5 +1,6 @@ --- '@firebase/ai': minor +'firebase': minor --- Added ability to specify thinking levels in `thinkingConfig`.