@ai-sdk/google-vertex 5.0.0-beta.11 → 5.0.0-beta.112
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 +954 -8
- package/README.md +65 -2
- package/dist/anthropic/edge/index.d.ts +18 -151
- package/dist/anthropic/edge/index.js +88 -70
- package/dist/anthropic/edge/index.js.map +1 -1
- package/dist/anthropic/index.d.ts +18 -151
- package/dist/anthropic/index.js +88 -81
- package/dist/anthropic/index.js.map +1 -1
- package/dist/edge/index.d.ts +49 -20
- package/dist/edge/index.js +629 -278
- package/dist/edge/index.js.map +1 -1
- package/dist/index.d.ts +61 -23
- package/dist/index.js +638 -296
- package/dist/index.js.map +1 -1
- package/dist/maas/edge/index.d.ts +76 -0
- package/dist/maas/edge/index.js +209 -0
- package/dist/maas/edge/index.js.map +1 -0
- package/dist/maas/index.d.ts +60 -0
- package/dist/maas/index.js +109 -0
- package/dist/maas/index.js.map +1 -0
- package/dist/xai/edge/index.d.ts +92 -0
- package/dist/xai/edge/index.js +259 -0
- package/dist/xai/edge/index.js.map +1 -0
- package/dist/xai/index.d.ts +76 -0
- package/dist/xai/index.js +159 -0
- package/dist/xai/index.js.map +1 -0
- package/docs/16-google-vertex.mdx +640 -102
- package/maas/edge.d.ts +1 -0
- package/maas/index.d.ts +1 -0
- package/package.json +49 -24
- package/src/anthropic/edge/google-vertex-anthropic-provider-edge.ts +17 -13
- package/src/anthropic/edge/index.ts +6 -2
- package/src/anthropic/{google-vertex-anthropic-messages-options.ts → google-vertex-anthropic-options.ts} +4 -1
- package/src/anthropic/google-vertex-anthropic-provider-node.ts +18 -13
- package/src/anthropic/google-vertex-anthropic-provider.ts +68 -19
- package/src/anthropic/index.ts +6 -2
- package/src/edge/google-vertex-provider-edge.ts +10 -12
- package/src/edge/index.ts +8 -1
- package/src/google-vertex-auth-google-auth-library.ts +13 -26
- package/src/google-vertex-config.ts +2 -2
- package/src/{google-vertex-embedding-options.ts → google-vertex-embedding-model-options.ts} +1 -0
- package/src/google-vertex-embedding-model.ts +90 -7
- package/src/google-vertex-image-model-options.ts +74 -0
- package/src/google-vertex-image-model.ts +89 -116
- package/src/google-vertex-options.ts +1 -1
- package/src/google-vertex-provider-base.ts +311 -0
- package/src/google-vertex-provider.ts +43 -233
- package/src/google-vertex-speech-model-options.ts +11 -0
- package/src/google-vertex-transcription-model-options.ts +46 -0
- package/src/google-vertex-transcription-model.ts +231 -0
- package/src/google-vertex-video-model-options.ts +49 -0
- package/src/google-vertex-video-model.ts +38 -71
- package/src/index.ts +20 -5
- package/src/maas/edge/google-vertex-maas-provider-edge.ts +64 -0
- package/src/maas/edge/index.ts +13 -0
- package/src/maas/google-vertex-maas-options.ts +15 -0
- package/src/maas/google-vertex-maas-provider-node.ts +65 -0
- package/src/maas/google-vertex-maas-provider.ts +122 -0
- package/src/maas/index.ts +13 -0
- package/src/xai/edge/google-vertex-xai-provider-edge.ts +61 -0
- package/src/xai/edge/index.ts +9 -0
- package/src/xai/google-vertex-xai-options.ts +7 -0
- package/src/xai/google-vertex-xai-provider-node.ts +62 -0
- package/src/xai/google-vertex-xai-provider.ts +212 -0
- package/src/xai/index.ts +9 -0
- package/xai/edge.d.ts +1 -0
- package/xai/index.d.ts +1 -0
- package/dist/anthropic/edge/index.d.mts +0 -231
- package/dist/anthropic/edge/index.mjs +0 -259
- package/dist/anthropic/edge/index.mjs.map +0 -1
- package/dist/anthropic/index.d.mts +0 -215
- package/dist/anthropic/index.mjs +0 -164
- package/dist/anthropic/index.mjs.map +0 -1
- package/dist/edge/index.d.mts +0 -160
- package/dist/edge/index.mjs +0 -1049
- package/dist/edge/index.mjs.map +0 -1
- package/dist/index.d.mts +0 -219
- package/dist/index.mjs +0 -960
- package/dist/index.mjs.map +0 -1
- package/src/google-vertex-provider-node.ts +0 -49
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
EmbeddingModelV4,
|
|
3
2
|
TooManyEmbeddingValuesForCallError,
|
|
3
|
+
type EmbeddingModelV4,
|
|
4
4
|
} from '@ai-sdk/provider';
|
|
5
5
|
import {
|
|
6
6
|
combineHeaders,
|
|
@@ -8,27 +8,49 @@ import {
|
|
|
8
8
|
postJsonToApi,
|
|
9
9
|
resolve,
|
|
10
10
|
parseProviderOptions,
|
|
11
|
+
serializeModelOptions,
|
|
12
|
+
WORKFLOW_SERIALIZE,
|
|
13
|
+
WORKFLOW_DESERIALIZE,
|
|
11
14
|
} from '@ai-sdk/provider-utils';
|
|
12
15
|
import { z } from 'zod/v4';
|
|
13
16
|
import { googleVertexFailedResponseHandler } from './google-vertex-error';
|
|
14
17
|
import {
|
|
15
|
-
GoogleVertexEmbeddingModelId,
|
|
16
18
|
googleVertexEmbeddingModelOptions,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
type GoogleVertexEmbeddingModelId,
|
|
20
|
+
} from './google-vertex-embedding-model-options';
|
|
21
|
+
import type { GoogleVertexConfig } from './google-vertex-config';
|
|
19
22
|
|
|
20
23
|
export class GoogleVertexEmbeddingModel implements EmbeddingModelV4 {
|
|
21
24
|
readonly specificationVersion = 'v4';
|
|
22
25
|
readonly modelId: GoogleVertexEmbeddingModelId;
|
|
23
|
-
readonly maxEmbeddingsPerCall = 2048;
|
|
24
26
|
readonly supportsParallelCalls = true;
|
|
25
27
|
|
|
26
28
|
private readonly config: GoogleVertexConfig;
|
|
27
29
|
|
|
30
|
+
static [WORKFLOW_SERIALIZE](model: GoogleVertexEmbeddingModel) {
|
|
31
|
+
return serializeModelOptions({
|
|
32
|
+
modelId: model.modelId,
|
|
33
|
+
config: model.config,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
38
|
+
modelId: string;
|
|
39
|
+
config: GoogleVertexConfig;
|
|
40
|
+
}) {
|
|
41
|
+
return new GoogleVertexEmbeddingModel(options.modelId, options.config);
|
|
42
|
+
}
|
|
43
|
+
|
|
28
44
|
get provider(): string {
|
|
29
45
|
return this.config.provider;
|
|
30
46
|
}
|
|
31
47
|
|
|
48
|
+
// gemini-embedding-2 models only support :embedContent (one value per call),
|
|
49
|
+
// not the :predict batch endpoint. https://github.com/vercel/ai/issues/15853
|
|
50
|
+
get maxEmbeddingsPerCall(): number {
|
|
51
|
+
return usesEmbedContentEndpoint(this.modelId) ? 1 : 2048;
|
|
52
|
+
}
|
|
53
|
+
|
|
32
54
|
constructor(
|
|
33
55
|
modelId: GoogleVertexEmbeddingModelId,
|
|
34
56
|
config: GoogleVertexConfig,
|
|
@@ -46,11 +68,19 @@ export class GoogleVertexEmbeddingModel implements EmbeddingModelV4 {
|
|
|
46
68
|
Awaited<ReturnType<EmbeddingModelV4['doEmbed']>>
|
|
47
69
|
> {
|
|
48
70
|
let googleOptions = await parseProviderOptions({
|
|
49
|
-
provider: '
|
|
71
|
+
provider: 'googleVertex',
|
|
50
72
|
providerOptions,
|
|
51
73
|
schema: googleVertexEmbeddingModelOptions,
|
|
52
74
|
});
|
|
53
75
|
|
|
76
|
+
if (googleOptions == null) {
|
|
77
|
+
googleOptions = await parseProviderOptions({
|
|
78
|
+
provider: 'vertex',
|
|
79
|
+
providerOptions,
|
|
80
|
+
schema: googleVertexEmbeddingModelOptions,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
54
84
|
if (googleOptions == null) {
|
|
55
85
|
googleOptions = await parseProviderOptions({
|
|
56
86
|
provider: 'google',
|
|
@@ -71,10 +101,46 @@ export class GoogleVertexEmbeddingModel implements EmbeddingModelV4 {
|
|
|
71
101
|
}
|
|
72
102
|
|
|
73
103
|
const mergedHeaders = combineHeaders(
|
|
74
|
-
await resolve(this.config.headers),
|
|
104
|
+
this.config.headers ? await resolve(this.config.headers) : undefined,
|
|
75
105
|
headers,
|
|
76
106
|
);
|
|
77
107
|
|
|
108
|
+
if (usesEmbedContentEndpoint(this.modelId)) {
|
|
109
|
+
const {
|
|
110
|
+
responseHeaders,
|
|
111
|
+
value: response,
|
|
112
|
+
rawValue,
|
|
113
|
+
} = await postJsonToApi({
|
|
114
|
+
url: `${this.config.baseURL}/models/${this.modelId}:embedContent`,
|
|
115
|
+
headers: mergedHeaders,
|
|
116
|
+
body: {
|
|
117
|
+
content: { parts: [{ text: values[0] }] },
|
|
118
|
+
embedContentConfig: {
|
|
119
|
+
outputDimensionality: googleOptions.outputDimensionality,
|
|
120
|
+
taskType: googleOptions.taskType,
|
|
121
|
+
title: googleOptions.title,
|
|
122
|
+
autoTruncate: googleOptions.autoTruncate,
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
126
|
+
successfulResponseHandler: createJsonResponseHandler(
|
|
127
|
+
googleVertexEmbedContentResponseSchema,
|
|
128
|
+
),
|
|
129
|
+
abortSignal,
|
|
130
|
+
fetch: this.config.fetch,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
warnings: [],
|
|
135
|
+
embeddings: [response.embedding.values],
|
|
136
|
+
usage:
|
|
137
|
+
response.usageMetadata?.promptTokenCount == null
|
|
138
|
+
? undefined
|
|
139
|
+
: { tokens: response.usageMetadata.promptTokenCount },
|
|
140
|
+
response: { headers: responseHeaders, body: rawValue },
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
78
144
|
const url = `${this.config.baseURL}/models/${this.modelId}:predict`;
|
|
79
145
|
const {
|
|
80
146
|
responseHeaders,
|
|
@@ -133,3 +199,20 @@ const googleVertexTextEmbeddingResponseSchema = z.object({
|
|
|
133
199
|
}),
|
|
134
200
|
),
|
|
135
201
|
});
|
|
202
|
+
|
|
203
|
+
const googleVertexEmbedContentResponseSchema = z.object({
|
|
204
|
+
embedding: z.object({
|
|
205
|
+
values: z.array(z.number()),
|
|
206
|
+
}),
|
|
207
|
+
usageMetadata: z
|
|
208
|
+
.object({
|
|
209
|
+
promptTokenCount: z.number().nullish(),
|
|
210
|
+
})
|
|
211
|
+
.nullish(),
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
function usesEmbedContentEndpoint(modelId: GoogleVertexEmbeddingModelId) {
|
|
215
|
+
return (
|
|
216
|
+
modelId === 'gemini-embedding-2' || modelId === 'gemini-embedding-2-preview'
|
|
217
|
+
);
|
|
218
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
|
|
3
|
+
export const googleVertexImageModelOptionsSchema = z.object({
|
|
4
|
+
negativePrompt: z.string().nullish(),
|
|
5
|
+
personGeneration: z
|
|
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
|
|
74
|
+
>;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { GoogleLanguageModelOptions } from '@ai-sdk/google';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { GoogleLanguageModel } from '@ai-sdk/google/internal';
|
|
3
|
+
import type {
|
|
4
4
|
ImageModelV4,
|
|
5
5
|
ImageModelV4File,
|
|
6
6
|
LanguageModelV4Prompt,
|
|
7
7
|
SharedV4Warning,
|
|
8
8
|
} from '@ai-sdk/provider';
|
|
9
9
|
import {
|
|
10
|
-
Resolvable,
|
|
11
10
|
combineHeaders,
|
|
12
11
|
convertToBase64,
|
|
13
12
|
convertUint8ArrayToBase64,
|
|
@@ -16,10 +15,15 @@ import {
|
|
|
16
15
|
parseProviderOptions,
|
|
17
16
|
postJsonToApi,
|
|
18
17
|
resolve,
|
|
18
|
+
serializeModelOptions,
|
|
19
|
+
WORKFLOW_SERIALIZE,
|
|
20
|
+
WORKFLOW_DESERIALIZE,
|
|
21
|
+
type Resolvable,
|
|
19
22
|
} from '@ai-sdk/provider-utils';
|
|
20
23
|
import { z } from 'zod/v4';
|
|
21
24
|
import { googleVertexFailedResponseHandler } from './google-vertex-error';
|
|
22
|
-
import {
|
|
25
|
+
import { googleVertexImageModelOptionsSchema } from './google-vertex-image-model-options';
|
|
26
|
+
import type { GoogleVertexImageModelId } from './google-vertex-image-settings';
|
|
23
27
|
|
|
24
28
|
interface GoogleVertexImageModelConfig {
|
|
25
29
|
provider: string;
|
|
@@ -36,6 +40,20 @@ interface GoogleVertexImageModelConfig {
|
|
|
36
40
|
export class GoogleVertexImageModel implements ImageModelV4 {
|
|
37
41
|
readonly specificationVersion = 'v4';
|
|
38
42
|
|
|
43
|
+
static [WORKFLOW_SERIALIZE](model: GoogleVertexImageModel) {
|
|
44
|
+
return serializeModelOptions({
|
|
45
|
+
modelId: model.modelId,
|
|
46
|
+
config: model.config,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
51
|
+
modelId: string;
|
|
52
|
+
config: GoogleVertexImageModelConfig;
|
|
53
|
+
}) {
|
|
54
|
+
return new GoogleVertexImageModel(options.modelId, options.config);
|
|
55
|
+
}
|
|
56
|
+
|
|
39
57
|
get maxImagesPerCall(): number {
|
|
40
58
|
if (isGeminiModel(this.modelId)) {
|
|
41
59
|
return 10;
|
|
@@ -86,14 +104,20 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
86
104
|
});
|
|
87
105
|
}
|
|
88
106
|
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
+
}));
|
|
94
118
|
|
|
95
119
|
// Extract edit-specific options from provider options
|
|
96
|
-
const { edit, ...otherOptions } =
|
|
120
|
+
const { edit, ...otherOptions } = googleVertexImageOptions ?? {};
|
|
97
121
|
const { mode: editMode, baseSteps, maskMode, maskDilation } = edit ?? {};
|
|
98
122
|
|
|
99
123
|
// Build the request body based on whether we're editing or generating
|
|
@@ -164,11 +188,14 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
164
188
|
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
165
189
|
const { value: response, responseHeaders } = await postJsonToApi({
|
|
166
190
|
url: `${this.config.baseURL}/models/${this.modelId}:predict`,
|
|
167
|
-
headers: combineHeaders(
|
|
191
|
+
headers: combineHeaders(
|
|
192
|
+
this.config.headers ? await resolve(this.config.headers) : undefined,
|
|
193
|
+
headers,
|
|
194
|
+
),
|
|
168
195
|
body,
|
|
169
196
|
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
170
197
|
successfulResponseHandler: createJsonResponseHandler(
|
|
171
|
-
|
|
198
|
+
googleVertexImageResponseSchema,
|
|
172
199
|
),
|
|
173
200
|
abortSignal,
|
|
174
201
|
fetch: this.config.fetch,
|
|
@@ -185,8 +212,8 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
185
212
|
modelId: this.modelId,
|
|
186
213
|
headers: responseHeaders,
|
|
187
214
|
},
|
|
188
|
-
providerMetadata: {
|
|
189
|
-
|
|
215
|
+
providerMetadata: (() => {
|
|
216
|
+
const payload = {
|
|
190
217
|
images:
|
|
191
218
|
response.predictions?.map(prediction => {
|
|
192
219
|
const {
|
|
@@ -196,8 +223,9 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
196
223
|
|
|
197
224
|
return { ...(revisedPrompt != null && { revisedPrompt }) };
|
|
198
225
|
}) ?? [],
|
|
199
|
-
}
|
|
200
|
-
|
|
226
|
+
};
|
|
227
|
+
return { googleVertex: payload, vertex: payload };
|
|
228
|
+
})(),
|
|
201
229
|
};
|
|
202
230
|
}
|
|
203
231
|
|
|
@@ -240,7 +268,13 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
240
268
|
|
|
241
269
|
const userContent: Array<
|
|
242
270
|
| { type: 'text'; text: string }
|
|
243
|
-
| {
|
|
271
|
+
| {
|
|
272
|
+
type: 'file';
|
|
273
|
+
data:
|
|
274
|
+
| { type: 'data'; data: string | Uint8Array }
|
|
275
|
+
| { type: 'url'; url: URL };
|
|
276
|
+
mediaType: string;
|
|
277
|
+
}
|
|
244
278
|
> = [];
|
|
245
279
|
|
|
246
280
|
if (prompt != null) {
|
|
@@ -252,16 +286,19 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
252
286
|
if (file.type === 'url') {
|
|
253
287
|
userContent.push({
|
|
254
288
|
type: 'file',
|
|
255
|
-
data: new URL(file.url),
|
|
289
|
+
data: { type: 'url', url: new URL(file.url) },
|
|
256
290
|
mediaType: 'image/*',
|
|
257
291
|
});
|
|
258
292
|
} else {
|
|
259
293
|
userContent.push({
|
|
260
294
|
type: 'file',
|
|
261
|
-
data:
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
295
|
+
data: {
|
|
296
|
+
type: 'data',
|
|
297
|
+
data:
|
|
298
|
+
typeof file.data === 'string'
|
|
299
|
+
? file.data
|
|
300
|
+
: new Uint8Array(file.data),
|
|
301
|
+
},
|
|
265
302
|
mediaType: file.mediaType,
|
|
266
303
|
});
|
|
267
304
|
}
|
|
@@ -272,7 +309,7 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
272
309
|
{ role: 'user', content: userContent },
|
|
273
310
|
];
|
|
274
311
|
|
|
275
|
-
const languageModel = new
|
|
312
|
+
const languageModel = new GoogleLanguageModel(this.modelId, {
|
|
276
313
|
provider: this.config.provider,
|
|
277
314
|
baseURL: this.config.baseURL,
|
|
278
315
|
headers: this.config.headers ?? {},
|
|
@@ -283,24 +320,27 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
283
320
|
}),
|
|
284
321
|
});
|
|
285
322
|
|
|
323
|
+
const userVertexOptions = (providerOptions?.googleVertex ??
|
|
324
|
+
providerOptions?.vertex) as
|
|
325
|
+
| Omit<GoogleLanguageModelOptions, 'responseModalities' | 'imageConfig'>
|
|
326
|
+
| undefined;
|
|
327
|
+
const innerVertexOptions: GoogleLanguageModelOptions = {
|
|
328
|
+
responseModalities: ['IMAGE'],
|
|
329
|
+
imageConfig: aspectRatio
|
|
330
|
+
? {
|
|
331
|
+
aspectRatio: aspectRatio as NonNullable<
|
|
332
|
+
GoogleLanguageModelOptions['imageConfig']
|
|
333
|
+
>['aspectRatio'],
|
|
334
|
+
}
|
|
335
|
+
: undefined,
|
|
336
|
+
...(userVertexOptions ?? {}),
|
|
337
|
+
};
|
|
286
338
|
const result = await languageModel.doGenerate({
|
|
287
339
|
prompt: languageModelPrompt,
|
|
288
340
|
seed,
|
|
289
341
|
providerOptions: {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
imageConfig: aspectRatio
|
|
293
|
-
? {
|
|
294
|
-
aspectRatio: aspectRatio as NonNullable<
|
|
295
|
-
GoogleLanguageModelOptions['imageConfig']
|
|
296
|
-
>['aspectRatio'],
|
|
297
|
-
}
|
|
298
|
-
: undefined,
|
|
299
|
-
...((providerOptions?.vertex as Omit<
|
|
300
|
-
GoogleLanguageModelOptions,
|
|
301
|
-
'responseModalities' | 'imageConfig'
|
|
302
|
-
>) ?? {}),
|
|
303
|
-
} satisfies GoogleLanguageModelOptions,
|
|
342
|
+
googleVertex: innerVertexOptions,
|
|
343
|
+
vertex: innerVertexOptions,
|
|
304
344
|
},
|
|
305
345
|
headers,
|
|
306
346
|
abortSignal,
|
|
@@ -310,18 +350,24 @@ export class GoogleVertexImageModel implements ImageModelV4 {
|
|
|
310
350
|
|
|
311
351
|
const images: string[] = [];
|
|
312
352
|
for (const part of result.content) {
|
|
313
|
-
if (
|
|
314
|
-
|
|
353
|
+
if (
|
|
354
|
+
part.type === 'file' &&
|
|
355
|
+
part.mediaType.startsWith('image/') &&
|
|
356
|
+
part.data.type === 'data'
|
|
357
|
+
) {
|
|
358
|
+
images.push(convertToBase64(part.data.data));
|
|
315
359
|
}
|
|
316
360
|
}
|
|
317
361
|
|
|
362
|
+
const geminiPayload = {
|
|
363
|
+
images: images.map(() => ({})),
|
|
364
|
+
};
|
|
318
365
|
return {
|
|
319
366
|
images,
|
|
320
367
|
warnings,
|
|
321
368
|
providerMetadata: {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
},
|
|
369
|
+
googleVertex: geminiPayload,
|
|
370
|
+
vertex: geminiPayload,
|
|
325
371
|
},
|
|
326
372
|
response: {
|
|
327
373
|
timestamp: currentDate,
|
|
@@ -347,7 +393,7 @@ function isGeminiModel(modelId: string): boolean {
|
|
|
347
393
|
|
|
348
394
|
// minimal version of the schema, focussed on what is needed for the implementation
|
|
349
395
|
// this approach limits breakages when the API changes and increases efficiency
|
|
350
|
-
const
|
|
396
|
+
const googleVertexImageResponseSchema = z.object({
|
|
351
397
|
predictions: z
|
|
352
398
|
.array(
|
|
353
399
|
z.object({
|
|
@@ -359,79 +405,6 @@ const vertexImageResponseSchema = z.object({
|
|
|
359
405
|
.nullish(),
|
|
360
406
|
});
|
|
361
407
|
|
|
362
|
-
const googleVertexImageModelOptionsSchema = z.object({
|
|
363
|
-
negativePrompt: z.string().nullish(),
|
|
364
|
-
personGeneration: z
|
|
365
|
-
.enum(['dont_allow', 'allow_adult', 'allow_all'])
|
|
366
|
-
.nullish(),
|
|
367
|
-
safetySetting: z
|
|
368
|
-
.enum([
|
|
369
|
-
'block_low_and_above',
|
|
370
|
-
'block_medium_and_above',
|
|
371
|
-
'block_only_high',
|
|
372
|
-
'block_none',
|
|
373
|
-
])
|
|
374
|
-
.nullish(),
|
|
375
|
-
addWatermark: z.boolean().nullish(),
|
|
376
|
-
storageUri: z.string().nullish(),
|
|
377
|
-
sampleImageSize: z.enum(['1K', '2K']).nullish(),
|
|
378
|
-
/**
|
|
379
|
-
* Configuration for image editing operations
|
|
380
|
-
*/
|
|
381
|
-
edit: z
|
|
382
|
-
.object({
|
|
383
|
-
/**
|
|
384
|
-
* An integer that represents the number of sampling steps.
|
|
385
|
-
* A higher value offers better image quality, a lower value offers better latency.
|
|
386
|
-
* Try 35 steps to start. If the quality doesn't meet your requirements,
|
|
387
|
-
* increase the value towards an upper limit of 75.
|
|
388
|
-
*/
|
|
389
|
-
baseSteps: z.number().nullish(),
|
|
390
|
-
|
|
391
|
-
// Edit mode options
|
|
392
|
-
// https://cloud.google.com/vertex-ai/generative-ai/docs/image/edit-insert-objects
|
|
393
|
-
mode: z
|
|
394
|
-
.enum([
|
|
395
|
-
'EDIT_MODE_INPAINT_INSERTION',
|
|
396
|
-
'EDIT_MODE_INPAINT_REMOVAL',
|
|
397
|
-
'EDIT_MODE_OUTPAINT',
|
|
398
|
-
'EDIT_MODE_CONTROLLED_EDITING',
|
|
399
|
-
'EDIT_MODE_PRODUCT_IMAGE',
|
|
400
|
-
'EDIT_MODE_BGSWAP',
|
|
401
|
-
])
|
|
402
|
-
.nullish(),
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* The mask mode to use.
|
|
406
|
-
* - `MASK_MODE_DEFAULT` - Default value for mask mode.
|
|
407
|
-
* - `MASK_MODE_USER_PROVIDED` - User provided mask. No segmentation needed.
|
|
408
|
-
* - `MASK_MODE_DETECTION_BOX` - Mask from detected bounding boxes.
|
|
409
|
-
* - `MASK_MODE_CLOTHING_AREA` - Masks from segmenting the clothing area with open-vocab segmentation.
|
|
410
|
-
* - `MASK_MODE_PARSED_PERSON` - Masks from segmenting the person body and clothing using the person-parsing model.
|
|
411
|
-
*/
|
|
412
|
-
maskMode: z
|
|
413
|
-
.enum([
|
|
414
|
-
'MASK_MODE_DEFAULT',
|
|
415
|
-
'MASK_MODE_USER_PROVIDED',
|
|
416
|
-
'MASK_MODE_DETECTION_BOX',
|
|
417
|
-
'MASK_MODE_CLOTHING_AREA',
|
|
418
|
-
'MASK_MODE_PARSED_PERSON',
|
|
419
|
-
])
|
|
420
|
-
.nullish(),
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Optional. A float value between 0 and 1, inclusive, that represents the
|
|
424
|
-
* percentage of the image width to grow the mask by. Using dilation helps
|
|
425
|
-
* compensate for imprecise masks. We recommend a value of 0.01.
|
|
426
|
-
*/
|
|
427
|
-
maskDilation: z.number().nullish(),
|
|
428
|
-
})
|
|
429
|
-
.nullish(),
|
|
430
|
-
});
|
|
431
|
-
export type GoogleVertexImageModelOptions = z.infer<
|
|
432
|
-
typeof googleVertexImageModelOptionsSchema
|
|
433
|
-
>;
|
|
434
|
-
|
|
435
408
|
/**
|
|
436
409
|
* Helper to convert ImageModelV4File data to base64 string
|
|
437
410
|
*/
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// https://console.cloud.google.com/vertex-ai/studio/
|
|
4
4
|
export type GoogleVertexModelId =
|
|
5
5
|
// Stable models
|
|
6
|
+
| 'gemini-3.5-flash'
|
|
6
7
|
| 'gemini-2.5-pro'
|
|
7
8
|
| 'gemini-2.5-flash'
|
|
8
9
|
| 'gemini-2.5-flash-lite'
|
|
@@ -21,7 +22,6 @@ export type GoogleVertexModelId =
|
|
|
21
22
|
| 'gemini-1.0-pro-002'
|
|
22
23
|
// Preview models
|
|
23
24
|
| 'gemini-2.0-flash-lite-preview-02-05'
|
|
24
|
-
| 'gemini-2.5-flash-lite-preview-09-2025'
|
|
25
25
|
| 'gemini-2.5-flash-preview-09-2025'
|
|
26
26
|
| 'gemini-3-pro-preview'
|
|
27
27
|
| 'gemini-3-pro-image-preview'
|