@ai-sdk/google-vertex 5.0.59 → 5.0.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/anthropic/edge/index.js +1 -1
- package/dist/edge/index.d.ts +1 -1
- package/dist/edge/index.js +124 -339
- package/dist/edge/index.js.map +1 -1
- package/dist/index.d.ts +3 -42
- package/dist/index.js +124 -339
- package/dist/index.js.map +1 -1
- package/dist/maas/edge/index.js +1 -1
- package/dist/xai/edge/index.js +1 -1
- package/docs/16-google-vertex.mdx +11 -208
- package/package.json +3 -3
- package/src/google-vertex-image-model-options.ts +4 -72
- package/src/google-vertex-image-model.ts +37 -232
- package/src/google-vertex-image-settings.ts +0 -6
|
@@ -996,198 +996,10 @@ The following optional provider options are available for Google Vertex AI embed
|
|
|
996
996
|
|
|
997
997
|
### Image Models
|
|
998
998
|
|
|
999
|
-
You can create image models using the `.image()` factory method.
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
[Imagen models](https://cloud.google.com/vertex-ai/generative-ai/docs/image/generate-images) generate images using the Imagen on Vertex AI API.
|
|
1004
|
-
|
|
1005
|
-
```ts
|
|
1006
|
-
import { googleVertex } from '@ai-sdk/google-vertex';
|
|
1007
|
-
import { generateImage } from 'ai';
|
|
1008
|
-
|
|
1009
|
-
const { image } = await generateImage({
|
|
1010
|
-
model: googleVertex.image('imagen-4.0-generate-001'),
|
|
1011
|
-
prompt: 'A futuristic cityscape at sunset',
|
|
1012
|
-
aspectRatio: '16:9',
|
|
1013
|
-
});
|
|
1014
|
-
```
|
|
1015
|
-
|
|
1016
|
-
Further configuration can be done using Google Vertex provider options. You can validate the provider options using the `GoogleVertexImageModelOptions` type.
|
|
1017
|
-
|
|
1018
|
-
```ts
|
|
1019
|
-
import { googleVertex } from '@ai-sdk/google-vertex';
|
|
1020
|
-
import { GoogleVertexImageModelOptions } from '@ai-sdk/google-vertex';
|
|
1021
|
-
import { generateImage } from 'ai';
|
|
1022
|
-
|
|
1023
|
-
const { image } = await generateImage({
|
|
1024
|
-
model: googleVertex.image('imagen-4.0-generate-001'),
|
|
1025
|
-
providerOptions: {
|
|
1026
|
-
vertex: {
|
|
1027
|
-
negativePrompt: 'pixelated, blurry, low-quality',
|
|
1028
|
-
} satisfies GoogleVertexImageModelOptions,
|
|
1029
|
-
},
|
|
1030
|
-
// ...
|
|
1031
|
-
});
|
|
1032
|
-
```
|
|
1033
|
-
|
|
1034
|
-
The following provider options are available:
|
|
1035
|
-
|
|
1036
|
-
- **negativePrompt** _string_
|
|
1037
|
-
A description of what to discourage in the generated images.
|
|
1038
|
-
|
|
1039
|
-
- **personGeneration** `allow_adult` | `allow_all` | `dont_allow`
|
|
1040
|
-
Whether to allow person generation. Defaults to `allow_adult`.
|
|
1041
|
-
|
|
1042
|
-
- **safetySetting** `block_low_and_above` | `block_medium_and_above` | `block_only_high` | `block_none`
|
|
1043
|
-
Whether to block unsafe content. Defaults to `block_medium_and_above`.
|
|
1044
|
-
|
|
1045
|
-
- **addWatermark** _boolean_
|
|
1046
|
-
Whether to add an invisible watermark to the generated images. Defaults to `true`.
|
|
1047
|
-
|
|
1048
|
-
- **storageUri** _string_
|
|
1049
|
-
Cloud Storage URI to store the generated images.
|
|
1050
|
-
|
|
1051
|
-
<Note>
|
|
1052
|
-
Imagen models do not support the `size` parameter. Use the `aspectRatio`
|
|
1053
|
-
parameter instead.
|
|
1054
|
-
</Note>
|
|
1055
|
-
|
|
1056
|
-
Additional information about the images can be retrieved using Google Vertex meta data.
|
|
1057
|
-
|
|
1058
|
-
```ts
|
|
1059
|
-
import { googleVertex } from '@ai-sdk/google-vertex';
|
|
1060
|
-
import { GoogleVertexImageModelOptions } from '@ai-sdk/google-vertex';
|
|
1061
|
-
import { generateImage } from 'ai';
|
|
1062
|
-
|
|
1063
|
-
const { image, providerMetadata } = await generateImage({
|
|
1064
|
-
model: googleVertex.image('imagen-4.0-generate-001'),
|
|
1065
|
-
prompt: 'A futuristic cityscape at sunset',
|
|
1066
|
-
aspectRatio: '16:9',
|
|
1067
|
-
});
|
|
1068
|
-
|
|
1069
|
-
console.log(
|
|
1070
|
-
`Revised prompt: ${providerMetadata.vertex.images[0].revisedPrompt}`,
|
|
1071
|
-
);
|
|
1072
|
-
```
|
|
1073
|
-
|
|
1074
|
-
##### Image Editing
|
|
1075
|
-
|
|
1076
|
-
Google Vertex Imagen models support image editing through inpainting, outpainting, and other edit modes. Pass input images via `prompt.images` and optionally a mask via `prompt.mask`.
|
|
1077
|
-
|
|
1078
|
-
<Note>
|
|
1079
|
-
Image editing is supported by `imagen-3.0-capability-001`. The
|
|
1080
|
-
`imagen-4.0-generate-001` model does not currently support editing operations.
|
|
1081
|
-
</Note>
|
|
1082
|
-
|
|
1083
|
-
###### Inpainting (Insert Objects)
|
|
1084
|
-
|
|
1085
|
-
Insert or replace objects in specific areas using a mask:
|
|
1086
|
-
|
|
1087
|
-
```ts
|
|
1088
|
-
import {
|
|
1089
|
-
googleVertex,
|
|
1090
|
-
GoogleVertexImageModelOptions,
|
|
1091
|
-
} from '@ai-sdk/google-vertex';
|
|
1092
|
-
import { generateImage } from 'ai';
|
|
1093
|
-
import fs from 'fs';
|
|
1094
|
-
|
|
1095
|
-
const image = fs.readFileSync('./input-image.png');
|
|
1096
|
-
const mask = fs.readFileSync('./mask.png'); // White = edit area
|
|
1097
|
-
|
|
1098
|
-
const { images } = await generateImage({
|
|
1099
|
-
model: googleVertex.image('imagen-3.0-capability-001'),
|
|
1100
|
-
prompt: {
|
|
1101
|
-
text: 'A sunlit indoor lounge area with a pool containing a flamingo',
|
|
1102
|
-
images: [image],
|
|
1103
|
-
mask,
|
|
1104
|
-
},
|
|
1105
|
-
providerOptions: {
|
|
1106
|
-
vertex: {
|
|
1107
|
-
edit: {
|
|
1108
|
-
baseSteps: 50,
|
|
1109
|
-
mode: 'EDIT_MODE_INPAINT_INSERTION',
|
|
1110
|
-
maskMode: 'MASK_MODE_USER_PROVIDED',
|
|
1111
|
-
maskDilation: 0.01,
|
|
1112
|
-
},
|
|
1113
|
-
} satisfies GoogleVertexImageModelOptions,
|
|
1114
|
-
},
|
|
1115
|
-
});
|
|
1116
|
-
```
|
|
1117
|
-
|
|
1118
|
-
###### Outpainting (Extend Image)
|
|
1119
|
-
|
|
1120
|
-
Extend an image beyond its original boundaries:
|
|
1121
|
-
|
|
1122
|
-
```ts
|
|
1123
|
-
import {
|
|
1124
|
-
googleVertex,
|
|
1125
|
-
GoogleVertexImageModelOptions,
|
|
1126
|
-
} from '@ai-sdk/google-vertex';
|
|
1127
|
-
import { generateImage } from 'ai';
|
|
1128
|
-
import fs from 'fs';
|
|
1129
|
-
|
|
1130
|
-
const image = fs.readFileSync('./input-image.png');
|
|
1131
|
-
const mask = fs.readFileSync('./outpaint-mask.png'); // White = extend area
|
|
1132
|
-
|
|
1133
|
-
const { images } = await generateImage({
|
|
1134
|
-
model: googleVertex.image('imagen-3.0-capability-001'),
|
|
1135
|
-
prompt: {
|
|
1136
|
-
text: 'Extend the scene with more of the forest background',
|
|
1137
|
-
images: [image],
|
|
1138
|
-
mask,
|
|
1139
|
-
},
|
|
1140
|
-
providerOptions: {
|
|
1141
|
-
vertex: {
|
|
1142
|
-
edit: {
|
|
1143
|
-
baseSteps: 50,
|
|
1144
|
-
mode: 'EDIT_MODE_OUTPAINT',
|
|
1145
|
-
maskMode: 'MASK_MODE_USER_PROVIDED',
|
|
1146
|
-
},
|
|
1147
|
-
} satisfies GoogleVertexImageModelOptions,
|
|
1148
|
-
},
|
|
1149
|
-
});
|
|
1150
|
-
```
|
|
1151
|
-
|
|
1152
|
-
###### Edit Provider Options
|
|
1153
|
-
|
|
1154
|
-
The following options are available under `providerOptions.vertex.edit`:
|
|
1155
|
-
|
|
1156
|
-
- **mode** - The edit mode to use:
|
|
1157
|
-
- `EDIT_MODE_INPAINT_INSERTION` - Insert objects into masked areas
|
|
1158
|
-
- `EDIT_MODE_INPAINT_REMOVAL` - Remove objects from masked areas
|
|
1159
|
-
- `EDIT_MODE_OUTPAINT` - Extend image beyond boundaries
|
|
1160
|
-
- `EDIT_MODE_CONTROLLED_EDITING` - Controlled editing
|
|
1161
|
-
- `EDIT_MODE_PRODUCT_IMAGE` - Product image editing
|
|
1162
|
-
- `EDIT_MODE_BGSWAP` - Background swap
|
|
1163
|
-
|
|
1164
|
-
- **baseSteps** _number_ - Number of sampling steps (35-75). Higher values = better quality but slower.
|
|
1165
|
-
|
|
1166
|
-
- **maskMode** - How to interpret the mask:
|
|
1167
|
-
- `MASK_MODE_USER_PROVIDED` - Use the provided mask directly
|
|
1168
|
-
- `MASK_MODE_DEFAULT` - Default mask mode
|
|
1169
|
-
- `MASK_MODE_DETECTION_BOX` - Mask from detected bounding boxes
|
|
1170
|
-
- `MASK_MODE_CLOTHING_AREA` - Mask from clothing segmentation
|
|
1171
|
-
- `MASK_MODE_PARSED_PERSON` - Mask from person parsing
|
|
1172
|
-
|
|
1173
|
-
- **maskDilation** _number_ - Percentage (0-1) to grow the mask. Recommended: 0.01.
|
|
1174
|
-
|
|
1175
|
-
<Note>
|
|
1176
|
-
Input images must be provided as `Buffer`, `ArrayBuffer`, `Uint8Array`, or
|
|
1177
|
-
base64-encoded strings. URL-based images are not supported for Google Vertex
|
|
1178
|
-
image editing.
|
|
1179
|
-
</Note>
|
|
1180
|
-
|
|
1181
|
-
##### Imagen Model Capabilities
|
|
1182
|
-
|
|
1183
|
-
| Model | Aspect Ratios |
|
|
1184
|
-
| ------------------------------- | ------------------------- |
|
|
1185
|
-
| `imagen-3.0-generate-001` | 1:1, 3:4, 4:3, 9:16, 16:9 |
|
|
1186
|
-
| `imagen-3.0-generate-002` | 1:1, 3:4, 4:3, 9:16, 16:9 |
|
|
1187
|
-
| `imagen-3.0-fast-generate-001` | 1:1, 3:4, 4:3, 9:16, 16:9 |
|
|
1188
|
-
| `imagen-4.0-generate-001` | 1:1, 3:4, 4:3, 9:16, 16:9 |
|
|
1189
|
-
| `imagen-4.0-fast-generate-001` | 1:1, 3:4, 4:3, 9:16, 16:9 |
|
|
1190
|
-
| `imagen-4.0-ultra-generate-001` | 1:1, 3:4, 4:3, 9:16, 16:9 |
|
|
999
|
+
You can create Gemini image models using the `.image()` factory method. These
|
|
1000
|
+
models provide image output through the language model `:generateContent` API.
|
|
1001
|
+
For more on image generation with the AI SDK see
|
|
1002
|
+
[generateImage()](/docs/reference/ai-sdk-core/generate-image).
|
|
1191
1003
|
|
|
1192
1004
|
#### Gemini Image Models
|
|
1193
1005
|
|
|
@@ -1222,20 +1034,11 @@ const { image } = await generateImage({
|
|
|
1222
1034
|
});
|
|
1223
1035
|
```
|
|
1224
1036
|
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
const { image } = await generateImage({
|
|
1232
|
-
model: googleVertex.image('gemini-2.5-flash-image'),
|
|
1233
|
-
prompt: {
|
|
1234
|
-
text: 'Add a small wizard hat to this cat',
|
|
1235
|
-
images: ['https://example.com/cat.png'],
|
|
1236
|
-
},
|
|
1237
|
-
});
|
|
1238
|
-
```
|
|
1037
|
+
<Note>
|
|
1038
|
+
Input images must be provided as `Buffer`, `ArrayBuffer`, `Uint8Array`, or
|
|
1039
|
+
base64-encoded strings. URL inputs, including HTTP and `gs://` URLs, are not
|
|
1040
|
+
supported by `generateImage()` with Google Vertex image models.
|
|
1041
|
+
</Note>
|
|
1239
1042
|
|
|
1240
1043
|
<Note>
|
|
1241
1044
|
Gemini image models do not support the `size` or `n` parameters. Use
|
|
@@ -1260,8 +1063,8 @@ const { image } = await generateImage({
|
|
|
1260
1063
|
<Note>
|
|
1261
1064
|
`gemini-3-pro-image-preview` supports additional features including up to 14
|
|
1262
1065
|
reference images for editing (6 objects, 5 humans), resolution options (1K,
|
|
1263
|
-
2K, 4K via `providerOptions.vertex.imageConfig.imageSize`)
|
|
1264
|
-
|
|
1066
|
+
2K, 4K via `providerOptions.vertex.imageConfig.imageSize`). Use the
|
|
1067
|
+
`GoogleVertexImageModelOptions` type to validate Gemini provider options.
|
|
1265
1068
|
</Note>
|
|
1266
1069
|
|
|
1267
1070
|
### Video Models
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/google-vertex",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.60",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -73,8 +73,8 @@
|
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"google-auth-library": "^10.6.2",
|
|
75
75
|
"@ai-sdk/anthropic": "4.0.40",
|
|
76
|
-
"@ai-sdk/google": "4.0.
|
|
77
|
-
"@ai-sdk/openai-compatible": "3.0.
|
|
76
|
+
"@ai-sdk/google": "4.0.49",
|
|
77
|
+
"@ai-sdk/openai-compatible": "3.0.34",
|
|
78
78
|
"@ai-sdk/provider": "4.0.7",
|
|
79
79
|
"@ai-sdk/provider-utils": "5.0.28"
|
|
80
80
|
},
|
|
@@ -1,74 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { GoogleLanguageModelOptions } from '@ai-sdk/google';
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
.enum(['dont_allow', 'allow_adult', 'allow_all'])
|
|
7
|
-
.nullish(),
|
|
8
|
-
safetySetting: z
|
|
9
|
-
.enum([
|
|
10
|
-
'block_low_and_above',
|
|
11
|
-
'block_medium_and_above',
|
|
12
|
-
'block_only_high',
|
|
13
|
-
'block_none',
|
|
14
|
-
])
|
|
15
|
-
.nullish(),
|
|
16
|
-
addWatermark: z.boolean().nullish(),
|
|
17
|
-
storageUri: z.string().nullish(),
|
|
18
|
-
sampleImageSize: z.enum(['1K', '2K']).nullish(),
|
|
19
|
-
/**
|
|
20
|
-
* Configuration for image editing operations
|
|
21
|
-
*/
|
|
22
|
-
edit: z
|
|
23
|
-
.object({
|
|
24
|
-
/**
|
|
25
|
-
* An integer that represents the number of sampling steps.
|
|
26
|
-
* A higher value offers better image quality, a lower value offers better latency.
|
|
27
|
-
* Try 35 steps to start. If the quality doesn't meet your requirements,
|
|
28
|
-
* increase the value towards an upper limit of 75.
|
|
29
|
-
*/
|
|
30
|
-
baseSteps: z.number().nullish(),
|
|
31
|
-
|
|
32
|
-
// Edit mode options
|
|
33
|
-
// https://cloud.google.com/vertex-ai/generative-ai/docs/image/edit-insert-objects
|
|
34
|
-
mode: z
|
|
35
|
-
.enum([
|
|
36
|
-
'EDIT_MODE_INPAINT_INSERTION',
|
|
37
|
-
'EDIT_MODE_INPAINT_REMOVAL',
|
|
38
|
-
'EDIT_MODE_OUTPAINT',
|
|
39
|
-
'EDIT_MODE_CONTROLLED_EDITING',
|
|
40
|
-
'EDIT_MODE_PRODUCT_IMAGE',
|
|
41
|
-
'EDIT_MODE_BGSWAP',
|
|
42
|
-
])
|
|
43
|
-
.nullish(),
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* The mask mode to use.
|
|
47
|
-
* - `MASK_MODE_DEFAULT` - Default value for mask mode.
|
|
48
|
-
* - `MASK_MODE_USER_PROVIDED` - User provided mask. No segmentation needed.
|
|
49
|
-
* - `MASK_MODE_DETECTION_BOX` - Mask from detected bounding boxes.
|
|
50
|
-
* - `MASK_MODE_CLOTHING_AREA` - Masks from segmenting the clothing area with open-vocab segmentation.
|
|
51
|
-
* - `MASK_MODE_PARSED_PERSON` - Masks from segmenting the person body and clothing using the person-parsing model.
|
|
52
|
-
*/
|
|
53
|
-
maskMode: z
|
|
54
|
-
.enum([
|
|
55
|
-
'MASK_MODE_DEFAULT',
|
|
56
|
-
'MASK_MODE_USER_PROVIDED',
|
|
57
|
-
'MASK_MODE_DETECTION_BOX',
|
|
58
|
-
'MASK_MODE_CLOTHING_AREA',
|
|
59
|
-
'MASK_MODE_PARSED_PERSON',
|
|
60
|
-
])
|
|
61
|
-
.nullish(),
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Optional. A float value between 0 and 1, inclusive, that represents the
|
|
65
|
-
* percentage of the image width to grow the mask by. Using dilation helps
|
|
66
|
-
* compensate for imprecise masks. We recommend a value of 0.01.
|
|
67
|
-
*/
|
|
68
|
-
maskDilation: z.number().nullish(),
|
|
69
|
-
})
|
|
70
|
-
.nullish(),
|
|
71
|
-
});
|
|
72
|
-
export type GoogleVertexImageModelOptions = z.infer<
|
|
73
|
-
typeof googleVertexImageModelOptionsSchema
|
|
3
|
+
export type GoogleVertexImageModelOptions = Omit<
|
|
4
|
+
GoogleLanguageModelOptions,
|
|
5
|
+
'responseModalities'
|
|
74
6
|
>;
|
|
@@ -2,27 +2,17 @@ import type { GoogleLanguageModelOptions } from '@ai-sdk/google';
|
|
|
2
2
|
import { GoogleLanguageModel } from '@ai-sdk/google/internal';
|
|
3
3
|
import type {
|
|
4
4
|
ImageModelV4,
|
|
5
|
-
ImageModelV4File,
|
|
6
5
|
LanguageModelV4Prompt,
|
|
7
6
|
SharedV4Warning,
|
|
8
7
|
} from '@ai-sdk/provider';
|
|
9
8
|
import {
|
|
10
|
-
combineHeaders,
|
|
11
9
|
convertToBase64,
|
|
12
|
-
convertUint8ArrayToBase64,
|
|
13
|
-
createJsonResponseHandler,
|
|
14
10
|
generateId as defaultGenerateId,
|
|
15
|
-
parseProviderOptions,
|
|
16
|
-
postJsonToApi,
|
|
17
|
-
resolve,
|
|
18
11
|
serializeModelOptions,
|
|
19
12
|
WORKFLOW_SERIALIZE,
|
|
20
13
|
WORKFLOW_DESERIALIZE,
|
|
21
14
|
type Resolvable,
|
|
22
15
|
} from '@ai-sdk/provider-utils';
|
|
23
|
-
import { z } from 'zod/v4';
|
|
24
|
-
import { googleVertexFailedResponseHandler } from './google-vertex-error';
|
|
25
|
-
import { googleVertexImageModelOptionsSchema } from './google-vertex-image-model-options';
|
|
26
16
|
import type { GoogleVertexImageModelId } from './google-vertex-image-settings';
|
|
27
17
|
|
|
28
18
|
interface GoogleVertexImageModelConfig {
|
|
@@ -36,7 +26,6 @@ interface GoogleVertexImageModelConfig {
|
|
|
36
26
|
};
|
|
37
27
|
}
|
|
38
28
|
|
|
39
|
-
// https://cloud.google.com/vertex-ai/generative-ai/docs/image/generate-images
|
|
40
29
|
export class GoogleVertexImageModel implements ImageModelV4 {
|
|
41
30
|
readonly specificationVersion = 'v4';
|
|
42
31
|
|
|
@@ -54,12 +43,7 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
54
43
|
return new GoogleVertexImageModel(options.modelId, options.config);
|
|
55
44
|
}
|
|
56
45
|
|
|
57
|
-
|
|
58
|
-
if (isGeminiModel(this.modelId)) {
|
|
59
|
-
return 10;
|
|
60
|
-
}
|
|
61
|
-
return 4;
|
|
62
|
-
}
|
|
46
|
+
readonly maxImagesPerCall = 10;
|
|
63
47
|
|
|
64
48
|
get provider(): string {
|
|
65
49
|
return this.config.provider;
|
|
@@ -73,176 +57,24 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
73
57
|
async doGenerate(
|
|
74
58
|
options: Parameters<ImageModelV4['doGenerate']>[0],
|
|
75
59
|
): Promise<Awaited<ReturnType<ImageModelV4['doGenerate']>>> {
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
private async doGenerateImagen({
|
|
83
|
-
prompt,
|
|
84
|
-
n,
|
|
85
|
-
size,
|
|
86
|
-
aspectRatio,
|
|
87
|
-
seed,
|
|
88
|
-
providerOptions,
|
|
89
|
-
headers,
|
|
90
|
-
abortSignal,
|
|
91
|
-
files,
|
|
92
|
-
mask,
|
|
93
|
-
}: Parameters<ImageModelV4['doGenerate']>[0]): Promise<
|
|
94
|
-
Awaited<ReturnType<ImageModelV4['doGenerate']>>
|
|
95
|
-
> {
|
|
96
|
-
const warnings: Array<SharedV4Warning> = [];
|
|
97
|
-
|
|
98
|
-
if (size != null) {
|
|
99
|
-
warnings.push({
|
|
100
|
-
type: 'unsupported',
|
|
101
|
-
feature: 'size',
|
|
102
|
-
details:
|
|
103
|
-
'This model does not support the `size` option. Use `aspectRatio` instead.',
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const googleVertexImageOptions =
|
|
108
|
-
(await parseProviderOptions({
|
|
109
|
-
provider: 'googleVertex',
|
|
110
|
-
providerOptions,
|
|
111
|
-
schema: googleVertexImageModelOptionsSchema,
|
|
112
|
-
})) ??
|
|
113
|
-
(await parseProviderOptions({
|
|
114
|
-
provider: 'vertex',
|
|
115
|
-
providerOptions,
|
|
116
|
-
schema: googleVertexImageModelOptionsSchema,
|
|
117
|
-
}));
|
|
118
|
-
|
|
119
|
-
// Extract edit-specific options from provider options
|
|
120
|
-
const { edit, ...otherOptions } = googleVertexImageOptions ?? {};
|
|
121
|
-
const { mode: editMode, baseSteps, maskMode, maskDilation } = edit ?? {};
|
|
122
|
-
|
|
123
|
-
// Build the request body based on whether we're editing or generating
|
|
124
|
-
const isEditMode = files != null && files.length > 0;
|
|
125
|
-
|
|
126
|
-
let body: Record<string, unknown>;
|
|
127
|
-
|
|
128
|
-
if (isEditMode) {
|
|
129
|
-
// Build reference images for editing
|
|
130
|
-
const referenceImages: Array<Record<string, unknown>> = [];
|
|
131
|
-
|
|
132
|
-
// Add the source image(s)
|
|
133
|
-
for (let i = 0; i < files.length; i++) {
|
|
134
|
-
const file = files[i];
|
|
135
|
-
referenceImages.push({
|
|
136
|
-
referenceType: 'REFERENCE_TYPE_RAW',
|
|
137
|
-
referenceId: i + 1,
|
|
138
|
-
referenceImage: {
|
|
139
|
-
bytesBase64Encoded: getBase64Data(file),
|
|
140
|
-
},
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Add mask if provided
|
|
145
|
-
if (mask != null) {
|
|
146
|
-
referenceImages.push({
|
|
147
|
-
referenceType: 'REFERENCE_TYPE_MASK',
|
|
148
|
-
referenceId: files.length + 1,
|
|
149
|
-
referenceImage: {
|
|
150
|
-
bytesBase64Encoded: getBase64Data(mask),
|
|
151
|
-
},
|
|
152
|
-
maskImageConfig: {
|
|
153
|
-
maskMode: maskMode ?? 'MASK_MODE_USER_PROVIDED',
|
|
154
|
-
...(maskDilation != null ? { dilation: maskDilation } : {}),
|
|
155
|
-
},
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
body = {
|
|
160
|
-
instances: [
|
|
161
|
-
{
|
|
162
|
-
prompt,
|
|
163
|
-
referenceImages,
|
|
164
|
-
},
|
|
165
|
-
],
|
|
166
|
-
parameters: {
|
|
167
|
-
sampleCount: n,
|
|
168
|
-
...(aspectRatio != null ? { aspectRatio } : {}),
|
|
169
|
-
...(seed != null ? { seed } : {}),
|
|
170
|
-
editMode: editMode ?? 'EDIT_MODE_INPAINT_INSERTION',
|
|
171
|
-
...(baseSteps != null ? { editConfig: { baseSteps } } : {}),
|
|
172
|
-
...otherOptions,
|
|
173
|
-
},
|
|
174
|
-
};
|
|
175
|
-
} else {
|
|
176
|
-
// Standard image generation
|
|
177
|
-
body = {
|
|
178
|
-
instances: [{ prompt }],
|
|
179
|
-
parameters: {
|
|
180
|
-
sampleCount: n,
|
|
181
|
-
...(aspectRatio != null ? { aspectRatio } : {}),
|
|
182
|
-
...(seed != null ? { seed } : {}),
|
|
183
|
-
...otherOptions,
|
|
184
|
-
},
|
|
185
|
-
};
|
|
60
|
+
if (!this.modelId.startsWith('gemini-')) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
'Google image models other than Gemini are no longer supported. Use a model ID that starts with `gemini-`.',
|
|
63
|
+
);
|
|
186
64
|
}
|
|
187
65
|
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
197
|
-
successfulResponseHandler: createJsonResponseHandler(
|
|
198
|
-
googleVertexImageResponseSchema,
|
|
199
|
-
),
|
|
66
|
+
const {
|
|
67
|
+
prompt,
|
|
68
|
+
n,
|
|
69
|
+
size,
|
|
70
|
+
aspectRatio,
|
|
71
|
+
seed,
|
|
72
|
+
providerOptions,
|
|
73
|
+
headers,
|
|
200
74
|
abortSignal,
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return {
|
|
205
|
-
images:
|
|
206
|
-
response.predictions?.map(
|
|
207
|
-
({ bytesBase64Encoded }) => bytesBase64Encoded,
|
|
208
|
-
) ?? [],
|
|
209
|
-
warnings,
|
|
210
|
-
response: {
|
|
211
|
-
timestamp: currentDate,
|
|
212
|
-
modelId: this.modelId,
|
|
213
|
-
headers: responseHeaders,
|
|
214
|
-
},
|
|
215
|
-
providerMetadata: (() => {
|
|
216
|
-
const payload = {
|
|
217
|
-
images:
|
|
218
|
-
response.predictions?.map(prediction => {
|
|
219
|
-
const {
|
|
220
|
-
// normalize revised prompt property
|
|
221
|
-
prompt: revisedPrompt,
|
|
222
|
-
} = prediction;
|
|
223
|
-
|
|
224
|
-
return { ...(revisedPrompt != null && { revisedPrompt }) };
|
|
225
|
-
}) ?? [],
|
|
226
|
-
};
|
|
227
|
-
return { googleVertex: payload, vertex: payload };
|
|
228
|
-
})(),
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
private async doGenerateGemini({
|
|
233
|
-
prompt,
|
|
234
|
-
n,
|
|
235
|
-
size,
|
|
236
|
-
aspectRatio,
|
|
237
|
-
seed,
|
|
238
|
-
providerOptions,
|
|
239
|
-
headers,
|
|
240
|
-
abortSignal,
|
|
241
|
-
files,
|
|
242
|
-
mask,
|
|
243
|
-
}: Parameters<ImageModelV4['doGenerate']>[0]): Promise<
|
|
244
|
-
Awaited<ReturnType<ImageModelV4['doGenerate']>>
|
|
245
|
-
> {
|
|
75
|
+
files,
|
|
76
|
+
mask,
|
|
77
|
+
} = options;
|
|
246
78
|
const warnings: Array<SharedV4Warning> = [];
|
|
247
79
|
|
|
248
80
|
if (mask != null) {
|
|
@@ -320,20 +152,29 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
320
152
|
}),
|
|
321
153
|
});
|
|
322
154
|
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
155
|
+
const {
|
|
156
|
+
responseModalities: _strippedResponseModalities,
|
|
157
|
+
imageConfig: userImageConfig,
|
|
158
|
+
...userVertexOptions
|
|
159
|
+
} = ((providerOptions?.googleVertex ?? providerOptions?.vertex) as
|
|
160
|
+
| GoogleLanguageModelOptions
|
|
161
|
+
| undefined) ?? {};
|
|
327
162
|
const innerVertexOptions: GoogleLanguageModelOptions = {
|
|
163
|
+
...userVertexOptions,
|
|
328
164
|
responseModalities: ['IMAGE'],
|
|
329
|
-
imageConfig:
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
165
|
+
imageConfig:
|
|
166
|
+
aspectRatio != null || userImageConfig != null
|
|
167
|
+
? {
|
|
168
|
+
...userImageConfig,
|
|
169
|
+
...(aspectRatio != null
|
|
170
|
+
? {
|
|
171
|
+
aspectRatio: aspectRatio as NonNullable<
|
|
172
|
+
GoogleLanguageModelOptions['imageConfig']
|
|
173
|
+
>['aspectRatio'],
|
|
174
|
+
}
|
|
175
|
+
: {}),
|
|
176
|
+
}
|
|
177
|
+
: undefined,
|
|
337
178
|
};
|
|
338
179
|
const result = await languageModel.doGenerate({
|
|
339
180
|
prompt: languageModelPrompt,
|
|
@@ -386,39 +227,3 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
386
227
|
};
|
|
387
228
|
}
|
|
388
229
|
}
|
|
389
|
-
|
|
390
|
-
function isGeminiModel(modelId: string): boolean {
|
|
391
|
-
return modelId.startsWith('gemini-');
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// minimal version of the schema, focussed on what is needed for the implementation
|
|
395
|
-
// this approach limits breakages when the API changes and increases efficiency
|
|
396
|
-
const googleVertexImageResponseSchema = z.object({
|
|
397
|
-
predictions: z
|
|
398
|
-
.array(
|
|
399
|
-
z.object({
|
|
400
|
-
bytesBase64Encoded: z.string(),
|
|
401
|
-
mimeType: z.string(),
|
|
402
|
-
prompt: z.string().nullish(),
|
|
403
|
-
}),
|
|
404
|
-
)
|
|
405
|
-
.nullish(),
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* Helper to convert ImageModelV4File data to base64 string
|
|
410
|
-
*/
|
|
411
|
-
function getBase64Data(file: ImageModelV4File): string {
|
|
412
|
-
if (file.type === 'url') {
|
|
413
|
-
throw new Error(
|
|
414
|
-
'URL-based images are not supported for Google Vertex image editing. Please provide the image data directly.',
|
|
415
|
-
);
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
if (typeof file.data === 'string') {
|
|
419
|
-
return file.data;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
// Convert Uint8Array to base64
|
|
423
|
-
return convertUint8ArrayToBase64(file.data);
|
|
424
|
-
}
|
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
export type GoogleVertexImageModelId =
|
|
2
|
-
| 'imagen-3.0-generate-001'
|
|
3
|
-
| 'imagen-3.0-generate-002'
|
|
4
|
-
| 'imagen-3.0-fast-generate-001'
|
|
5
|
-
| 'imagen-4.0-generate-001'
|
|
6
|
-
| 'imagen-4.0-ultra-generate-001'
|
|
7
|
-
| 'imagen-4.0-fast-generate-001'
|
|
8
2
|
| 'gemini-2.5-flash-image'
|
|
9
3
|
| 'gemini-3-pro-image-preview'
|
|
10
4
|
| 'gemini-3.1-flash-image-preview'
|