Skip to content

Commit c39015c

Browse files
authoredMay 8, 2024··
fix text() and add FileState (#131)
1 parent bc79f48 commit c39015c

8 files changed

+163
-40
lines changed
 

‎.changeset/two-queens-boil.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@google/generative-ai": patch
3+
---
4+
5+
Fixed a bug where `text()` did not handle multiple `TextPart`s in a single candidate. Added `state` field to `FileMetadataResponse`.

‎docs/reference/files/generative-ai.filemetadataresponse.md

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export interface FileMetadataResponse
2323
| [name](./generative-ai.filemetadataresponse.name.md) | | string | |
2424
| [sha256Hash](./generative-ai.filemetadataresponse.sha256hash.md) | | string | |
2525
| [sizeBytes](./generative-ai.filemetadataresponse.sizebytes.md) | | string | |
26+
| [state](./generative-ai.filemetadataresponse.state.md) | | [FileState](./generative-ai.filestate.md) | |
2627
| [updateTime](./generative-ai.filemetadataresponse.updatetime.md) | | string | |
2728
| [uri](./generative-ai.filemetadataresponse.uri.md) | | string | |
2829

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
2+
3+
[Home](./index.md) &gt; [@google/generative-ai](./generative-ai.md) &gt; [FileMetadataResponse](./generative-ai.filemetadataresponse.md) &gt; [state](./generative-ai.filemetadataresponse.state.md)
4+
5+
## FileMetadataResponse.state property
6+
7+
**Signature:**
8+
9+
```typescript
10+
state: FileState;
11+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
2+
3+
[Home](./index.md) &gt; [@google/generative-ai](./generative-ai.md) &gt; [FileState](./generative-ai.filestate.md)
4+
5+
## FileState enum
6+
7+
Processing state of the `File`<!-- -->.
8+
9+
**Signature:**
10+
11+
```typescript
12+
export declare enum FileState
13+
```
14+
15+
## Enumeration Members
16+
17+
| Member | Value | Description |
18+
| --- | --- | --- |
19+
| ACTIVE | <code>2</code> | |
20+
| FAILED | <code>10</code> | |
21+
| PROCESSING | <code>1</code> | |
22+
| STATE\_UNSPECIFIED | <code>0</code> | |
23+

‎docs/reference/files/generative-ai.md

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
| --- | --- |
1111
| [GoogleAIFileManager](./generative-ai.googleaifilemanager.md) | Class for managing GoogleAI file uploads. |
1212

13+
## Enumerations
14+
15+
| Enumeration | Description |
16+
| --- | --- |
17+
| [FileState](./generative-ai.filestate.md) | Processing state of the <code>File</code>. |
18+
1319
## Interfaces
1420

1521
| Interface | Description |

‎packages/main/src/files/types.ts

+16
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export interface FileMetadataResponse {
4848
expirationTime: string;
4949
sha256Hash: string;
5050
uri: string;
51+
state: FileState;
5152
}
5253

5354
/**
@@ -66,3 +67,18 @@ export interface ListFilesResponse {
6667
export interface UploadFileResponse {
6768
file: FileMetadataResponse;
6869
}
70+
71+
/**
72+
* Processing state of the `File`.
73+
* @public
74+
*/
75+
export enum FileState {
76+
// The default value. This value is used if the state is omitted.
77+
STATE_UNSPECIFIED = 0,
78+
// File is being processed and cannot be used for inference yet.
79+
PROCESSING = 1,
80+
// File is processed and available for inference.
81+
ACTIVE = 2,
82+
// File failed processing.
83+
FAILED = 10,
84+
}

‎packages/main/src/requests/response-helpers.test.ts

+90-35
Original file line numberDiff line numberDiff line change
@@ -40,54 +40,85 @@ const fakeResponseText: GenerateContentResponse = {
4040
],
4141
};
4242

43+
const functionCallPart1 = {
44+
functionCall: {
45+
name: "find_theaters",
46+
args: {
47+
location: "Mountain View, CA",
48+
movie: "Barbie",
49+
},
50+
},
51+
};
52+
53+
const functionCallPart2 = {
54+
functionCall: {
55+
name: "find_times",
56+
args: {
57+
location: "Mountain View, CA",
58+
movie: "Barbie",
59+
time: "20:00",
60+
},
61+
},
62+
};
63+
4364
const fakeResponseFunctionCall: GenerateContentResponse = {
4465
candidates: [
4566
{
4667
index: 0,
4768
content: {
4869
role: "model",
49-
parts: [
50-
{
51-
functionCall: {
52-
name: "find_theaters",
53-
args: {
54-
location: "Mountain View, CA",
55-
movie: "Barbie",
56-
},
57-
},
58-
},
59-
],
70+
parts: [functionCallPart1],
6071
},
6172
},
6273
],
6374
};
6475

6576
const fakeResponseFunctionCalls: GenerateContentResponse = {
77+
candidates: [
78+
{
79+
index: 0,
80+
content: {
81+
role: "model",
82+
parts: [functionCallPart1, functionCallPart2],
83+
},
84+
},
85+
],
86+
};
87+
88+
const fakeResponseMixed1: GenerateContentResponse = {
89+
candidates: [
90+
{
91+
index: 0,
92+
content: {
93+
role: "model",
94+
parts: [{ text: "some text" }, functionCallPart2],
95+
},
96+
},
97+
],
98+
};
99+
100+
const fakeResponseMixed2: GenerateContentResponse = {
101+
candidates: [
102+
{
103+
index: 0,
104+
content: {
105+
role: "model",
106+
parts: [functionCallPart1, { text: "some text" }],
107+
},
108+
},
109+
],
110+
};
111+
112+
const fakeResponseMixed3: GenerateContentResponse = {
66113
candidates: [
67114
{
68115
index: 0,
69116
content: {
70117
role: "model",
71118
parts: [
72-
{
73-
functionCall: {
74-
name: "find_theaters",
75-
args: {
76-
location: "Mountain View, CA",
77-
movie: "Barbie",
78-
},
79-
},
80-
},
81-
{
82-
functionCall: {
83-
name: "find_times",
84-
args: {
85-
location: "Mountain View, CA",
86-
movie: "Barbie",
87-
time: "20:00",
88-
},
89-
},
90-
},
119+
{ text: "some text" },
120+
functionCallPart1,
121+
{ text: " and more text" },
91122
],
92123
},
93124
},
@@ -109,19 +140,43 @@ describe("response-helpers methods", () => {
109140
it("good response text", async () => {
110141
const enhancedResponse = addHelpers(fakeResponseText);
111142
expect(enhancedResponse.text()).to.equal("Some text and some more text");
143+
expect(enhancedResponse.functionCalls()).to.be.undefined;
112144
});
113145
it("good response functionCall", async () => {
114146
const enhancedResponse = addHelpers(fakeResponseFunctionCall);
115-
expect(enhancedResponse.functionCall()).to.deep.equal(
116-
fakeResponseFunctionCall.candidates[0].content.parts[0].functionCall,
117-
);
147+
expect(enhancedResponse.text()).to.equal("");
148+
expect(enhancedResponse.functionCalls()).to.deep.equal([
149+
functionCallPart1.functionCall,
150+
]);
118151
});
119152
it("good response functionCalls", async () => {
120153
const enhancedResponse = addHelpers(fakeResponseFunctionCalls);
154+
expect(enhancedResponse.text()).to.equal("");
155+
expect(enhancedResponse.functionCalls()).to.deep.equal([
156+
functionCallPart1.functionCall,
157+
functionCallPart2.functionCall,
158+
]);
159+
});
160+
it("good response text/functionCall", async () => {
161+
const enhancedResponse = addHelpers(fakeResponseMixed1);
162+
expect(enhancedResponse.functionCalls()).to.deep.equal([
163+
functionCallPart2.functionCall,
164+
]);
165+
expect(enhancedResponse.text()).to.equal("some text");
166+
});
167+
it("good response functionCall/text", async () => {
168+
const enhancedResponse = addHelpers(fakeResponseMixed2);
169+
expect(enhancedResponse.functionCalls()).to.deep.equal([
170+
functionCallPart1.functionCall,
171+
]);
172+
expect(enhancedResponse.text()).to.equal("some text");
173+
});
174+
it("good response text/functionCall/text", async () => {
175+
const enhancedResponse = addHelpers(fakeResponseMixed3);
121176
expect(enhancedResponse.functionCalls()).to.deep.equal([
122-
fakeResponseFunctionCalls.candidates[0].content.parts[0].functionCall,
123-
fakeResponseFunctionCalls.candidates[0].content.parts[1].functionCall,
177+
functionCallPart1.functionCall,
124178
]);
179+
expect(enhancedResponse.text()).to.equal("some text and more text");
125180
});
126181
it("bad response safety", async () => {
127182
const enhancedResponse = addHelpers(badFakeResponse);

‎packages/main/src/requests/response-helpers.ts

+11-5
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,19 @@ export function addHelpers(
114114
}
115115

116116
/**
117-
* Returns text of first candidate.
117+
* Returns all text found in all parts of first candidate.
118118
*/
119119
export function getText(response: GenerateContentResponse): string {
120-
if (response.candidates?.[0].content?.parts?.[0]?.text) {
121-
return response.candidates[0].content.parts
122-
.map(({ text }) => text)
123-
.join("");
120+
const textStrings = [];
121+
if (response.candidates?.[0].content?.parts) {
122+
for (const part of response.candidates?.[0].content?.parts) {
123+
if (part.text) {
124+
textStrings.push(part.text);
125+
}
126+
}
127+
}
128+
if (textStrings.length > 0) {
129+
return textStrings.join("");
124130
} else {
125131
return "";
126132
}

0 commit comments

Comments
 (0)
Please sign in to comment.