Skip to content

Commit 7f1b37e

Browse files
authored
Merge fb7085a into 2058432
2 parents 2058432 + fb7085a commit 7f1b37e

17 files changed

+372
-79
lines changed

.changeset/brave-llamas-impress.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@firebase/ai': minor
3+
'firebase': minor
4+
---
5+
6+
Add `thoughtSummary()` convenience method to `EnhancedGenerateContentResponse`.

common/api-review/ai.api.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,10 @@ export { Date_2 as Date }
213213

214214
// @public
215215
export interface EnhancedGenerateContentResponse extends GenerateContentResponse {
216-
// (undocumented)
217216
functionCalls: () => FunctionCall[] | undefined;
218217
inlineDataParts: () => InlineDataPart[] | undefined;
219218
text: () => string;
219+
thoughtSummary: () => string | undefined;
220220
}
221221

222222
// @public
@@ -249,6 +249,10 @@ export interface FileDataPart {
249249
inlineData?: never;
250250
// (undocumented)
251251
text?: never;
252+
// (undocumented)
253+
thought?: boolean;
254+
// @internal (undocumented)
255+
thoughtSignature?: never;
252256
}
253257

254258
// @public
@@ -303,6 +307,10 @@ export interface FunctionCallPart {
303307
inlineData?: never;
304308
// (undocumented)
305309
text?: never;
310+
// (undocumented)
311+
thought?: boolean;
312+
// @internal (undocumented)
313+
thoughtSignature?: never;
306314
}
307315

308316
// @public
@@ -335,6 +343,10 @@ export interface FunctionResponsePart {
335343
inlineData?: never;
336344
// (undocumented)
337345
text?: never;
346+
// (undocumented)
347+
thought?: boolean;
348+
// @internal (undocumented)
349+
thoughtSignature?: never;
338350
}
339351

340352
// @public
@@ -717,6 +729,10 @@ export interface InlineDataPart {
717729
inlineData: GenerativeContentBlob;
718730
// (undocumented)
719731
text?: never;
732+
// (undocumented)
733+
thought?: boolean;
734+
// @internal (undocumented)
735+
thoughtSignature?: never;
720736
videoMetadata?: VideoMetadata;
721737
}
722738

@@ -1048,10 +1064,15 @@ export interface TextPart {
10481064
inlineData?: never;
10491065
// (undocumented)
10501066
text: string;
1067+
// (undocumented)
1068+
thought?: boolean;
1069+
// @internal (undocumented)
1070+
thoughtSignature?: string;
10511071
}
10521072

10531073
// @public
10541074
export interface ThinkingConfig {
1075+
includeThoughts?: boolean;
10551076
thinkingBudget?: number;
10561077
}
10571078

docs-devsite/ai.enhancedgeneratecontentresponse.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@ export interface EnhancedGenerateContentResponse extends GenerateContentResponse
2323
2424
| Property | Type | Description |
2525
| --- | --- | --- |
26-
| [functionCalls](./ai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponsefunctioncalls) | () =&gt; [FunctionCall](./ai.functioncall.md#functioncall_interface)<!-- -->\[\] \| undefined | |
27-
| [inlineDataParts](./ai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponseinlinedataparts) | () =&gt; [InlineDataPart](./ai.inlinedatapart.md#inlinedatapart_interface)<!-- -->\[\] \| undefined | Aggregates and returns all [InlineDataPart](./ai.inlinedatapart.md#inlinedatapart_interface)<!-- -->s from the [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->'s first candidate. |
26+
| [functionCalls](./ai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponsefunctioncalls) | () =&gt; [FunctionCall](./ai.functioncall.md#functioncall_interface)<!-- -->\[\] \| undefined | Aggregates and returns every [FunctionCall](./ai.functioncall.md#functioncall_interface) from the first candidate of [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->. |
27+
| [inlineDataParts](./ai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponseinlinedataparts) | () =&gt; [InlineDataPart](./ai.inlinedatapart.md#inlinedatapart_interface)<!-- -->\[\] \| undefined | Aggregates and returns every [InlineDataPart](./ai.inlinedatapart.md#inlinedatapart_interface) from the first candidate of [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->. |
2828
| [text](./ai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponsetext) | () =&gt; string | Returns the text string from the response, if available. Throws if the prompt or candidate was blocked. |
29+
| [thoughtSummary](./ai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponsethoughtsummary) | () =&gt; string \| undefined | Aggregates and returns every [TextPart](./ai.textpart.md#textpart_interface) with their <code>thought</code> property set to <code>true</code> from the first candidate of [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->. |
2930
3031
## EnhancedGenerateContentResponse.functionCalls
3132
33+
Aggregates and returns every [FunctionCall](./ai.functioncall.md#functioncall_interface) from the first candidate of [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->.
34+
3235
<b>Signature:</b>
3336
3437
```typescript
@@ -37,7 +40,7 @@ functionCalls: () => FunctionCall[] | undefined;
3740
3841
## EnhancedGenerateContentResponse.inlineDataParts
3942
40-
Aggregates and returns all [InlineDataPart](./ai.inlinedatapart.md#inlinedatapart_interface)<!-- -->s from the [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->'s first candidate.
43+
Aggregates and returns every [InlineDataPart](./ai.inlinedatapart.md#inlinedatapart_interface) from the first candidate of [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->.
4144
4245
<b>Signature:</b>
4346
@@ -54,3 +57,17 @@ Returns the text string from the response, if available. Throws if the prompt or
5457
```typescript
5558
text: () => string;
5659
```
60+
61+
## EnhancedGenerateContentResponse.thoughtSummary
62+
63+
Aggregates and returns every [TextPart](./ai.textpart.md#textpart_interface) with their `thought` property set to `true` from the first candidate of [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->.
64+
65+
Thought summaries provide a brief overview of the model's internal thinking process, offering insight into how it arrived at the final answer. This can be useful for debugging, understanding the model's reasoning, and verifying its accuracy.
66+
67+
Thoughts will only be included if [ThinkingConfig.includeThoughts](./ai.thinkingconfig.md#thinkingconfigincludethoughts) is set to `true`<!-- -->.
68+
69+
<b>Signature:</b>
70+
71+
```typescript
72+
thoughtSummary: () => string | undefined;
73+
```

docs-devsite/ai.filedatapart.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface FileDataPart
2727
| [functionResponse](./ai.filedatapart.md#filedatapartfunctionresponse) | never | |
2828
| [inlineData](./ai.filedatapart.md#filedatapartinlinedata) | never | |
2929
| [text](./ai.filedatapart.md#filedataparttext) | never | |
30+
| [thought](./ai.filedatapart.md#filedatapartthought) | boolean | |
3031

3132
## FileDataPart.fileData
3233

@@ -67,3 +68,11 @@ inlineData?: never;
6768
```typescript
6869
text?: never;
6970
```
71+
72+
## FileDataPart.thought
73+
74+
<b>Signature:</b>
75+
76+
```typescript
77+
thought?: boolean;
78+
```

docs-devsite/ai.functioncallpart.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export interface FunctionCallPart
2626
| [functionResponse](./ai.functioncallpart.md#functioncallpartfunctionresponse) | never | |
2727
| [inlineData](./ai.functioncallpart.md#functioncallpartinlinedata) | never | |
2828
| [text](./ai.functioncallpart.md#functioncallparttext) | never | |
29+
| [thought](./ai.functioncallpart.md#functioncallpartthought) | boolean | |
2930

3031
## FunctionCallPart.functionCall
3132

@@ -58,3 +59,11 @@ inlineData?: never;
5859
```typescript
5960
text?: never;
6061
```
62+
63+
## FunctionCallPart.thought
64+
65+
<b>Signature:</b>
66+
67+
```typescript
68+
thought?: boolean;
69+
```

docs-devsite/ai.functionresponsepart.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export interface FunctionResponsePart
2626
| [functionResponse](./ai.functionresponsepart.md#functionresponsepartfunctionresponse) | [FunctionResponse](./ai.functionresponse.md#functionresponse_interface) | |
2727
| [inlineData](./ai.functionresponsepart.md#functionresponsepartinlinedata) | never | |
2828
| [text](./ai.functionresponsepart.md#functionresponseparttext) | never | |
29+
| [thought](./ai.functionresponsepart.md#functionresponsepartthought) | boolean | |
2930

3031
## FunctionResponsePart.functionCall
3132

@@ -58,3 +59,11 @@ inlineData?: never;
5859
```typescript
5960
text?: never;
6061
```
62+
63+
## FunctionResponsePart.thought
64+
65+
<b>Signature:</b>
66+
67+
```typescript
68+
thought?: boolean;
69+
```

docs-devsite/ai.inlinedatapart.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export interface InlineDataPart
2626
| [functionResponse](./ai.inlinedatapart.md#inlinedatapartfunctionresponse) | never | |
2727
| [inlineData](./ai.inlinedatapart.md#inlinedatapartinlinedata) | [GenerativeContentBlob](./ai.generativecontentblob.md#generativecontentblob_interface) | |
2828
| [text](./ai.inlinedatapart.md#inlinedataparttext) | never | |
29+
| [thought](./ai.inlinedatapart.md#inlinedatapartthought) | boolean | |
2930
| [videoMetadata](./ai.inlinedatapart.md#inlinedatapartvideometadata) | [VideoMetadata](./ai.videometadata.md#videometadata_interface) | Applicable if <code>inlineData</code> is a video. |
3031

3132
## InlineDataPart.functionCall
@@ -60,6 +61,14 @@ inlineData: GenerativeContentBlob;
6061
text?: never;
6162
```
6263

64+
## InlineDataPart.thought
65+
66+
<b>Signature:</b>
67+
68+
```typescript
69+
thought?: boolean;
70+
```
71+
6372
## InlineDataPart.videoMetadata
6473

6574
Applicable if `inlineData` is a video.

docs-devsite/ai.textpart.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export interface TextPart
2626
| [functionResponse](./ai.textpart.md#textpartfunctionresponse) | never | |
2727
| [inlineData](./ai.textpart.md#textpartinlinedata) | never | |
2828
| [text](./ai.textpart.md#textparttext) | string | |
29+
| [thought](./ai.textpart.md#textpartthought) | boolean | |
2930

3031
## TextPart.functionCall
3132

@@ -58,3 +59,11 @@ inlineData?: never;
5859
```typescript
5960
text: string;
6061
```
62+
63+
## TextPart.thought
64+
65+
<b>Signature:</b>
66+
67+
```typescript
68+
thought?: boolean;
69+
```

docs-devsite/ai.thinkingconfig.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,21 @@ export interface ThinkingConfig
2424

2525
| Property | Type | Description |
2626
| --- | --- | --- |
27+
| [includeThoughts](./ai.thinkingconfig.md#thinkingconfigincludethoughts) | boolean | Whether to include "thought summaries" in the model's response. |
2728
| [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. |
2829

30+
## ThinkingConfig.includeThoughts
31+
32+
Whether to include "thought summaries" in the model's response.
33+
34+
Thought summaries provide a brief overview of the model's internal thinking process, offering insight into how it arrived at the final answer. This can be useful for debugging, understanding the model's reasoning, and verifying its accuracy.
35+
36+
<b>Signature:</b>
37+
38+
```typescript
39+
includeThoughts?: boolean;
40+
```
41+
2942
## ThinkingConfig.thinkingBudget
3043

3144
The thinking budget, in tokens.

packages/ai/src/methods/chat-session-helpers.test.ts

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ import { FirebaseError } from '@firebase/util';
2222

2323
describe('chat-session-helpers', () => {
2424
describe('validateChatHistory', () => {
25-
const TCS: Array<{ history: Content[]; isValid: boolean }> = [
25+
const TCS: Array<{
26+
history: Content[];
27+
isValid: boolean;
28+
errorShouldInclude?: string;
29+
}> = [
2630
{
2731
history: [{ role: 'user', parts: [{ text: 'hi' }] }],
2832
isValid: true
@@ -99,19 +103,23 @@ describe('chat-session-helpers', () => {
99103
{
100104
//@ts-expect-error
101105
history: [{ role: 'user', parts: '' }],
106+
errorShouldInclude: `array of Parts`,
102107
isValid: false
103108
},
104109
{
105110
//@ts-expect-error
106111
history: [{ role: 'user' }],
112+
errorShouldInclude: `array of Parts`,
107113
isValid: false
108114
},
109115
{
110116
history: [{ role: 'user', parts: [] }],
117+
errorShouldInclude: `at least one part`,
111118
isValid: false
112119
},
113120
{
114121
history: [{ role: 'model', parts: [{ text: 'hi' }] }],
122+
errorShouldInclude: `model`,
115123
isValid: false
116124
},
117125
{
@@ -125,13 +133,15 @@ describe('chat-session-helpers', () => {
125133
]
126134
}
127135
],
136+
errorShouldInclude: `function`,
128137
isValid: false
129138
},
130139
{
131140
history: [
132141
{ role: 'user', parts: [{ text: 'hi' }] },
133142
{ role: 'user', parts: [{ text: 'hi' }] }
134143
],
144+
errorShouldInclude: `can't follow 'user'`,
135145
isValid: false
136146
},
137147
{
@@ -140,6 +150,45 @@ describe('chat-session-helpers', () => {
140150
{ role: 'model', parts: [{ text: 'hi' }] },
141151
{ role: 'model', parts: [{ text: 'hi' }] }
142152
],
153+
errorShouldInclude: `can't follow 'model'`,
154+
isValid: false
155+
},
156+
{
157+
history: [
158+
{ role: 'user', parts: [{ text: 'hi' }] },
159+
{
160+
role: 'model',
161+
parts: [
162+
{ text: 'hi' },
163+
{
164+
text: 'thought about hi',
165+
thought: true,
166+
thoughtSignature: 'thought signature'
167+
}
168+
]
169+
}
170+
],
171+
isValid: true
172+
},
173+
{
174+
history: [
175+
{
176+
role: 'user',
177+
parts: [{ text: 'hi', thought: true, thoughtSignature: 'sig' }]
178+
},
179+
{
180+
role: 'model',
181+
parts: [
182+
{ text: 'hi' },
183+
{
184+
text: 'thought about hi',
185+
thought: true,
186+
thoughtSignature: 'thought signature'
187+
}
188+
]
189+
}
190+
],
191+
errorShouldInclude: 'thought',
143192
isValid: false
144193
}
145194
];
@@ -149,7 +198,14 @@ describe('chat-session-helpers', () => {
149198
if (tc.isValid) {
150199
expect(fn).to.not.throw();
151200
} else {
152-
expect(fn).to.throw(FirebaseError);
201+
try {
202+
fn();
203+
} catch (e) {
204+
expect(e).to.be.instanceOf(FirebaseError);
205+
if (e instanceof FirebaseError && tc.errorShouldInclude) {
206+
expect(e.message).to.include(tc.errorShouldInclude);
207+
}
208+
}
153209
}
154210
});
155211
});

0 commit comments

Comments
 (0)