Skip to content

Commit 0f106fc

Browse files
committed
[Firebase AI] Add thought summary and signature support
1 parent 4923537 commit 0f106fc

File tree

5 files changed

+53
-4
lines changed

5 files changed

+53
-4
lines changed

common/api-review/ai.api.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ export interface EnhancedGenerateContentResponse extends GenerateContentResponse
208208
functionCalls: () => FunctionCall[] | undefined;
209209
inlineDataParts: () => InlineDataPart[] | undefined;
210210
text: () => string;
211+
// (undocumented)
212+
thoughtSummary: () => string | undefined;
211213
}
212214

213215
// @public
@@ -240,6 +242,10 @@ export interface FileDataPart {
240242
inlineData?: never;
241243
// (undocumented)
242244
text?: never;
245+
// (undocumented)
246+
thought?: boolean;
247+
// (undocumented)
248+
thoughtSignature?: string;
243249
}
244250

245251
// @public
@@ -294,6 +300,10 @@ export interface FunctionCallPart {
294300
inlineData?: never;
295301
// (undocumented)
296302
text?: never;
303+
// (undocumented)
304+
thought?: boolean;
305+
// (undocumented)
306+
thoughtSignature?: string;
297307
}
298308

299309
// @public
@@ -326,6 +336,10 @@ export interface FunctionResponsePart {
326336
inlineData?: never;
327337
// (undocumented)
328338
text?: never;
339+
// (undocumented)
340+
thought?: boolean;
341+
// (undocumented)
342+
thoughtSignature?: string;
329343
}
330344

331345
// @public
@@ -691,6 +705,10 @@ export interface InlineDataPart {
691705
inlineData: GenerativeContentBlob;
692706
// (undocumented)
693707
text?: never;
708+
// (undocumented)
709+
thought?: boolean;
710+
// (undocumented)
711+
thoughtSignature?: string;
694712
videoMetadata?: VideoMetadata;
695713
}
696714

@@ -957,10 +975,15 @@ export interface TextPart {
957975
inlineData?: never;
958976
// (undocumented)
959977
text: string;
978+
// (undocumented)
979+
thought?: boolean;
980+
// (undocumented)
981+
thoughtSignature?: string;
960982
}
961983

962984
// @public
963985
export interface ThinkingConfig {
986+
includeThoughts?: boolean;
964987
thinkingBudget?: number;
965988
}
966989

packages/ai/src/requests/response-helpers.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export function addHelpers(
7878
}
7979
);
8080
}
81-
return getText(response);
81+
return getText(response, false);
8282
} else if (response.promptFeedback) {
8383
throw new AIError(
8484
AIErrorCode.RESPONSE_ERROR,
@@ -160,13 +160,19 @@ export function addHelpers(
160160
}
161161

162162
/**
163-
* Returns all text found in all parts of first candidate.
163+
* Returns all text from the first candidate's parts, filtering by whether they
164+
* are part of the model's 'thought' process.
165+
*
166+
* @param response - The {@link GenerateContentResponse} from which to extract text.
167+
* @param isThought - If `true`, extracts text from `thought` parts of the response,
168+
* which represent the model's internal reasoning. If `false`, extracts text from
169+
* regular response parts.
164170
*/
165-
export function getText(response: GenerateContentResponse): string {
171+
export function getText(response: GenerateContentResponse, isThought: boolean): string {
166172
const textStrings = [];
167173
if (response.candidates?.[0].content?.parts) {
168174
for (const part of response.candidates?.[0].content?.parts) {
169-
if (part.text) {
175+
if (part.text && (part.thought ?? false) === isThought) {
170176
textStrings.push(part.text);
171177
}
172178
}

packages/ai/src/types/content.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export interface TextPart {
4747
inlineData?: never;
4848
functionCall?: never;
4949
functionResponse?: never;
50+
thought?: boolean;
51+
thoughtSignature?: string;
5052
}
5153

5254
/**
@@ -62,6 +64,8 @@ export interface InlineDataPart {
6264
* Applicable if `inlineData` is a video.
6365
*/
6466
videoMetadata?: VideoMetadata;
67+
thought?: boolean;
68+
thoughtSignature?: string;
6569
}
6670

6771
/**
@@ -90,6 +94,8 @@ export interface FunctionCallPart {
9094
inlineData?: never;
9195
functionCall: FunctionCall;
9296
functionResponse?: never;
97+
thought?: boolean;
98+
thoughtSignature?: string;
9399
}
94100

95101
/**
@@ -101,6 +107,8 @@ export interface FunctionResponsePart {
101107
inlineData?: never;
102108
functionCall?: never;
103109
functionResponse: FunctionResponse;
110+
thought?: boolean;
111+
thoughtSignature?: string;
104112
}
105113

106114
/**
@@ -113,6 +121,8 @@ export interface FileDataPart {
113121
functionCall?: never;
114122
functionResponse?: never;
115123
fileData: FileData;
124+
thought?: boolean;
125+
thoughtSignature?: string;
116126
}
117127

118128
/**

packages/ai/src/types/requests.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,4 +294,13 @@ export interface ThinkingConfig {
294294
* feature or if the specified budget is not within the model's supported range.
295295
*/
296296
thinkingBudget?: number;
297+
298+
/**
299+
* Whether to include "thought summaries" in the model's response.
300+
*
301+
* Thought summaries provide a brief overview of the model's internal thinking process,
302+
* offering insight into how it arrived at the final answer. This can be useful for
303+
* debugging, understanding the model's reasoning, and verifying its accuracy.
304+
*/
305+
includeThoughts?: boolean;
297306
}

packages/ai/src/types/responses.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export interface EnhancedGenerateContentResponse
6969
*/
7070
inlineDataParts: () => InlineDataPart[] | undefined;
7171
functionCalls: () => FunctionCall[] | undefined;
72+
thoughtSummary: () => string | undefined;
7273
}
7374

7475
/**

0 commit comments

Comments
 (0)