@depup/ai-sdk__google 3.0.43-depup.0
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 +2531 -0
- package/LICENSE +13 -0
- package/README.md +25 -0
- package/changes.json +5 -0
- package/dist/index.d.mts +367 -0
- package/dist/index.d.ts +367 -0
- package/dist/index.js +2404 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2454 -0
- package/dist/index.mjs.map +1 -0
- package/dist/internal/index.d.mts +283 -0
- package/dist/internal/index.d.ts +283 -0
- package/dist/internal/index.js +1670 -0
- package/dist/internal/index.js.map +1 -0
- package/dist/internal/index.mjs +1678 -0
- package/dist/internal/index.mjs.map +1 -0
- package/docs/15-google-generative-ai.mdx +1298 -0
- package/internal.d.ts +1 -0
- package/package.json +96 -0
- package/src/convert-google-generative-ai-usage.ts +51 -0
- package/src/convert-json-schema-to-openapi-schema.ts +158 -0
- package/src/convert-to-google-generative-ai-messages.ts +236 -0
- package/src/get-model-path.ts +3 -0
- package/src/google-error.ts +26 -0
- package/src/google-generative-ai-embedding-model.ts +159 -0
- package/src/google-generative-ai-embedding-options.ts +51 -0
- package/src/google-generative-ai-image-model.ts +359 -0
- package/src/google-generative-ai-image-settings.ts +17 -0
- package/src/google-generative-ai-language-model.ts +1056 -0
- package/src/google-generative-ai-options.ts +198 -0
- package/src/google-generative-ai-prompt.ts +38 -0
- package/src/google-generative-ai-video-model.ts +374 -0
- package/src/google-generative-ai-video-settings.ts +8 -0
- package/src/google-prepare-tools.ts +254 -0
- package/src/google-provider.ts +227 -0
- package/src/google-supported-file-url.ts +20 -0
- package/src/google-tools.ts +71 -0
- package/src/index.ts +29 -0
- package/src/internal/index.ts +3 -0
- package/src/map-google-generative-ai-finish-reason.ts +29 -0
- package/src/tool/code-execution.ts +35 -0
- package/src/tool/enterprise-web-search.ts +18 -0
- package/src/tool/file-search.ts +51 -0
- package/src/tool/google-maps.ts +14 -0
- package/src/tool/google-search.ts +43 -0
- package/src/tool/url-context.ts +16 -0
- package/src/tool/vertex-rag-store.ts +31 -0
- package/src/version.ts +6 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EmbeddingModelV3,
|
|
3
|
+
TooManyEmbeddingValuesForCallError,
|
|
4
|
+
} from '@ai-sdk/provider';
|
|
5
|
+
import {
|
|
6
|
+
combineHeaders,
|
|
7
|
+
createJsonResponseHandler,
|
|
8
|
+
FetchFunction,
|
|
9
|
+
lazySchema,
|
|
10
|
+
parseProviderOptions,
|
|
11
|
+
postJsonToApi,
|
|
12
|
+
resolve,
|
|
13
|
+
zodSchema,
|
|
14
|
+
} from '@ai-sdk/provider-utils';
|
|
15
|
+
import { z } from 'zod/v4';
|
|
16
|
+
import { googleFailedResponseHandler } from './google-error';
|
|
17
|
+
import {
|
|
18
|
+
GoogleGenerativeAIEmbeddingModelId,
|
|
19
|
+
googleEmbeddingModelOptions,
|
|
20
|
+
} from './google-generative-ai-embedding-options';
|
|
21
|
+
|
|
22
|
+
type GoogleGenerativeAIEmbeddingConfig = {
|
|
23
|
+
provider: string;
|
|
24
|
+
baseURL: string;
|
|
25
|
+
headers: () => Record<string, string | undefined>;
|
|
26
|
+
fetch?: FetchFunction;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
|
|
30
|
+
readonly specificationVersion = 'v3';
|
|
31
|
+
readonly modelId: GoogleGenerativeAIEmbeddingModelId;
|
|
32
|
+
readonly maxEmbeddingsPerCall = 2048;
|
|
33
|
+
readonly supportsParallelCalls = true;
|
|
34
|
+
|
|
35
|
+
private readonly config: GoogleGenerativeAIEmbeddingConfig;
|
|
36
|
+
|
|
37
|
+
get provider(): string {
|
|
38
|
+
return this.config.provider;
|
|
39
|
+
}
|
|
40
|
+
constructor(
|
|
41
|
+
modelId: GoogleGenerativeAIEmbeddingModelId,
|
|
42
|
+
config: GoogleGenerativeAIEmbeddingConfig,
|
|
43
|
+
) {
|
|
44
|
+
this.modelId = modelId;
|
|
45
|
+
this.config = config;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async doEmbed({
|
|
49
|
+
values,
|
|
50
|
+
headers,
|
|
51
|
+
abortSignal,
|
|
52
|
+
providerOptions,
|
|
53
|
+
}: Parameters<EmbeddingModelV3['doEmbed']>[0]): Promise<
|
|
54
|
+
Awaited<ReturnType<EmbeddingModelV3['doEmbed']>>
|
|
55
|
+
> {
|
|
56
|
+
// Parse provider options
|
|
57
|
+
const googleOptions = await parseProviderOptions({
|
|
58
|
+
provider: 'google',
|
|
59
|
+
providerOptions,
|
|
60
|
+
schema: googleEmbeddingModelOptions,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
if (values.length > this.maxEmbeddingsPerCall) {
|
|
64
|
+
throw new TooManyEmbeddingValuesForCallError({
|
|
65
|
+
provider: this.provider,
|
|
66
|
+
modelId: this.modelId,
|
|
67
|
+
maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
|
|
68
|
+
values,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const mergedHeaders = combineHeaders(
|
|
73
|
+
await resolve(this.config.headers),
|
|
74
|
+
headers,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// For single embeddings, use the single endpoint (ratelimits, etc.)
|
|
78
|
+
if (values.length === 1) {
|
|
79
|
+
const {
|
|
80
|
+
responseHeaders,
|
|
81
|
+
value: response,
|
|
82
|
+
rawValue,
|
|
83
|
+
} = await postJsonToApi({
|
|
84
|
+
url: `${this.config.baseURL}/models/${this.modelId}:embedContent`,
|
|
85
|
+
headers: mergedHeaders,
|
|
86
|
+
body: {
|
|
87
|
+
model: `models/${this.modelId}`,
|
|
88
|
+
content: {
|
|
89
|
+
parts: [{ text: values[0] }],
|
|
90
|
+
},
|
|
91
|
+
outputDimensionality: googleOptions?.outputDimensionality,
|
|
92
|
+
taskType: googleOptions?.taskType,
|
|
93
|
+
},
|
|
94
|
+
failedResponseHandler: googleFailedResponseHandler,
|
|
95
|
+
successfulResponseHandler: createJsonResponseHandler(
|
|
96
|
+
googleGenerativeAISingleEmbeddingResponseSchema,
|
|
97
|
+
),
|
|
98
|
+
abortSignal,
|
|
99
|
+
fetch: this.config.fetch,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
warnings: [],
|
|
104
|
+
embeddings: [response.embedding.values],
|
|
105
|
+
usage: undefined,
|
|
106
|
+
response: { headers: responseHeaders, body: rawValue },
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const {
|
|
111
|
+
responseHeaders,
|
|
112
|
+
value: response,
|
|
113
|
+
rawValue,
|
|
114
|
+
} = await postJsonToApi({
|
|
115
|
+
url: `${this.config.baseURL}/models/${this.modelId}:batchEmbedContents`,
|
|
116
|
+
headers: mergedHeaders,
|
|
117
|
+
body: {
|
|
118
|
+
requests: values.map(value => ({
|
|
119
|
+
model: `models/${this.modelId}`,
|
|
120
|
+
content: { role: 'user', parts: [{ text: value }] },
|
|
121
|
+
outputDimensionality: googleOptions?.outputDimensionality,
|
|
122
|
+
taskType: googleOptions?.taskType,
|
|
123
|
+
})),
|
|
124
|
+
},
|
|
125
|
+
failedResponseHandler: googleFailedResponseHandler,
|
|
126
|
+
successfulResponseHandler: createJsonResponseHandler(
|
|
127
|
+
googleGenerativeAITextEmbeddingResponseSchema,
|
|
128
|
+
),
|
|
129
|
+
abortSignal,
|
|
130
|
+
fetch: this.config.fetch,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
warnings: [],
|
|
135
|
+
embeddings: response.embeddings.map(item => item.values),
|
|
136
|
+
usage: undefined,
|
|
137
|
+
response: { headers: responseHeaders, body: rawValue },
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// minimal version of the schema, focussed on what is needed for the implementation
|
|
143
|
+
// this approach limits breakages when the API changes and increases efficiency
|
|
144
|
+
const googleGenerativeAITextEmbeddingResponseSchema = lazySchema(() =>
|
|
145
|
+
zodSchema(
|
|
146
|
+
z.object({
|
|
147
|
+
embeddings: z.array(z.object({ values: z.array(z.number()) })),
|
|
148
|
+
}),
|
|
149
|
+
),
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
// Schema for single embedding response
|
|
153
|
+
const googleGenerativeAISingleEmbeddingResponseSchema = lazySchema(() =>
|
|
154
|
+
zodSchema(
|
|
155
|
+
z.object({
|
|
156
|
+
embedding: z.object({ values: z.array(z.number()) }),
|
|
157
|
+
}),
|
|
158
|
+
),
|
|
159
|
+
);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type InferSchema,
|
|
3
|
+
lazySchema,
|
|
4
|
+
zodSchema,
|
|
5
|
+
} from '@ai-sdk/provider-utils';
|
|
6
|
+
import { z } from 'zod/v4';
|
|
7
|
+
|
|
8
|
+
export type GoogleGenerativeAIEmbeddingModelId =
|
|
9
|
+
| 'gemini-embedding-001'
|
|
10
|
+
| (string & {});
|
|
11
|
+
|
|
12
|
+
export const googleEmbeddingModelOptions = lazySchema(() =>
|
|
13
|
+
zodSchema(
|
|
14
|
+
z.object({
|
|
15
|
+
/**
|
|
16
|
+
* Optional. Optional reduced dimension for the output embedding.
|
|
17
|
+
* If set, excessive values in the output embedding are truncated from the end.
|
|
18
|
+
*/
|
|
19
|
+
outputDimensionality: z.number().optional(),
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Optional. Specifies the task type for generating embeddings.
|
|
23
|
+
* Supported task types:
|
|
24
|
+
* - SEMANTIC_SIMILARITY: Optimized for text similarity.
|
|
25
|
+
* - CLASSIFICATION: Optimized for text classification.
|
|
26
|
+
* - CLUSTERING: Optimized for clustering texts based on similarity.
|
|
27
|
+
* - RETRIEVAL_DOCUMENT: Optimized for document retrieval.
|
|
28
|
+
* - RETRIEVAL_QUERY: Optimized for query-based retrieval.
|
|
29
|
+
* - QUESTION_ANSWERING: Optimized for answering questions.
|
|
30
|
+
* - FACT_VERIFICATION: Optimized for verifying factual information.
|
|
31
|
+
* - CODE_RETRIEVAL_QUERY: Optimized for retrieving code blocks based on natural language queries.
|
|
32
|
+
*/
|
|
33
|
+
taskType: z
|
|
34
|
+
.enum([
|
|
35
|
+
'SEMANTIC_SIMILARITY',
|
|
36
|
+
'CLASSIFICATION',
|
|
37
|
+
'CLUSTERING',
|
|
38
|
+
'RETRIEVAL_DOCUMENT',
|
|
39
|
+
'RETRIEVAL_QUERY',
|
|
40
|
+
'QUESTION_ANSWERING',
|
|
41
|
+
'FACT_VERIFICATION',
|
|
42
|
+
'CODE_RETRIEVAL_QUERY',
|
|
43
|
+
])
|
|
44
|
+
.optional(),
|
|
45
|
+
}),
|
|
46
|
+
),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export type GoogleEmbeddingModelOptions = InferSchema<
|
|
50
|
+
typeof googleEmbeddingModelOptions
|
|
51
|
+
>;
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ImageModelV3,
|
|
3
|
+
LanguageModelV3Prompt,
|
|
4
|
+
SharedV3Warning,
|
|
5
|
+
} from '@ai-sdk/provider';
|
|
6
|
+
import {
|
|
7
|
+
combineHeaders,
|
|
8
|
+
convertToBase64,
|
|
9
|
+
createJsonResponseHandler,
|
|
10
|
+
FetchFunction,
|
|
11
|
+
generateId as defaultGenerateId,
|
|
12
|
+
type InferSchema,
|
|
13
|
+
lazySchema,
|
|
14
|
+
parseProviderOptions,
|
|
15
|
+
postJsonToApi,
|
|
16
|
+
Resolvable,
|
|
17
|
+
resolve,
|
|
18
|
+
zodSchema,
|
|
19
|
+
} from '@ai-sdk/provider-utils';
|
|
20
|
+
import { z } from 'zod/v4';
|
|
21
|
+
import { googleFailedResponseHandler } from './google-error';
|
|
22
|
+
import {
|
|
23
|
+
GoogleGenerativeAIImageModelId,
|
|
24
|
+
GoogleGenerativeAIImageSettings,
|
|
25
|
+
} from './google-generative-ai-image-settings';
|
|
26
|
+
import { GoogleGenerativeAILanguageModel } from './google-generative-ai-language-model';
|
|
27
|
+
import type { GoogleLanguageModelOptions } from './google-generative-ai-options';
|
|
28
|
+
|
|
29
|
+
interface GoogleGenerativeAIImageModelConfig {
|
|
30
|
+
provider: string;
|
|
31
|
+
baseURL: string;
|
|
32
|
+
headers?: Resolvable<Record<string, string | undefined>>;
|
|
33
|
+
fetch?: FetchFunction;
|
|
34
|
+
generateId?: () => string;
|
|
35
|
+
_internal?: {
|
|
36
|
+
currentDate?: () => Date;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class GoogleGenerativeAIImageModel implements ImageModelV3 {
|
|
41
|
+
readonly specificationVersion = 'v3';
|
|
42
|
+
|
|
43
|
+
get maxImagesPerCall(): number {
|
|
44
|
+
if (this.settings.maxImagesPerCall != null) {
|
|
45
|
+
return this.settings.maxImagesPerCall;
|
|
46
|
+
}
|
|
47
|
+
// https://docs.cloud.google.com/vertex-ai/generative-ai/docs/models/gemini/2-5-flash-image
|
|
48
|
+
if (isGeminiModel(this.modelId)) {
|
|
49
|
+
return 10;
|
|
50
|
+
}
|
|
51
|
+
// https://ai.google.dev/gemini-api/docs/imagen#imagen-model
|
|
52
|
+
return 4;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get provider(): string {
|
|
56
|
+
return this.config.provider;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
constructor(
|
|
60
|
+
readonly modelId: GoogleGenerativeAIImageModelId,
|
|
61
|
+
private readonly settings: GoogleGenerativeAIImageSettings,
|
|
62
|
+
private readonly config: GoogleGenerativeAIImageModelConfig,
|
|
63
|
+
) {}
|
|
64
|
+
|
|
65
|
+
async doGenerate(
|
|
66
|
+
options: Parameters<ImageModelV3['doGenerate']>[0],
|
|
67
|
+
): Promise<Awaited<ReturnType<ImageModelV3['doGenerate']>>> {
|
|
68
|
+
// Gemini image models use the language model API internally
|
|
69
|
+
if (isGeminiModel(this.modelId)) {
|
|
70
|
+
return this.doGenerateGemini(options);
|
|
71
|
+
}
|
|
72
|
+
return this.doGenerateImagen(options);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private async doGenerateImagen(
|
|
76
|
+
options: Parameters<ImageModelV3['doGenerate']>[0],
|
|
77
|
+
): Promise<Awaited<ReturnType<ImageModelV3['doGenerate']>>> {
|
|
78
|
+
const {
|
|
79
|
+
prompt,
|
|
80
|
+
n = 1,
|
|
81
|
+
size,
|
|
82
|
+
aspectRatio = '1:1',
|
|
83
|
+
seed,
|
|
84
|
+
providerOptions,
|
|
85
|
+
headers,
|
|
86
|
+
abortSignal,
|
|
87
|
+
files,
|
|
88
|
+
mask,
|
|
89
|
+
} = options;
|
|
90
|
+
const warnings: Array<SharedV3Warning> = [];
|
|
91
|
+
|
|
92
|
+
// Imagen API endpoints do not support image editing
|
|
93
|
+
if (files != null && files.length > 0) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
'Google Generative AI does not support image editing with Imagen models. ' +
|
|
96
|
+
'Use Google Vertex AI (@ai-sdk/google-vertex) for image editing capabilities.',
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (mask != null) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
'Google Generative AI does not support image editing with masks. ' +
|
|
103
|
+
'Use Google Vertex AI (@ai-sdk/google-vertex) for image editing capabilities.',
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (size != null) {
|
|
108
|
+
warnings.push({
|
|
109
|
+
type: 'unsupported',
|
|
110
|
+
feature: 'size',
|
|
111
|
+
details:
|
|
112
|
+
'This model does not support the `size` option. Use `aspectRatio` instead.',
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (seed != null) {
|
|
117
|
+
warnings.push({
|
|
118
|
+
type: 'unsupported',
|
|
119
|
+
feature: 'seed',
|
|
120
|
+
details:
|
|
121
|
+
'This model does not support the `seed` option through this provider.',
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const googleOptions = await parseProviderOptions({
|
|
126
|
+
provider: 'google',
|
|
127
|
+
providerOptions,
|
|
128
|
+
schema: googleImageModelOptionsSchema,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
132
|
+
|
|
133
|
+
const parameters: Record<string, unknown> = {
|
|
134
|
+
sampleCount: n,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
if (aspectRatio != null) {
|
|
138
|
+
parameters.aspectRatio = aspectRatio;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (googleOptions) {
|
|
142
|
+
Object.assign(parameters, googleOptions);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const body = {
|
|
146
|
+
instances: [{ prompt }],
|
|
147
|
+
parameters,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const { responseHeaders, value: response } = await postJsonToApi<{
|
|
151
|
+
predictions: Array<{ bytesBase64Encoded: string }>;
|
|
152
|
+
}>({
|
|
153
|
+
url: `${this.config.baseURL}/models/${this.modelId}:predict`,
|
|
154
|
+
headers: combineHeaders(await resolve(this.config.headers), headers),
|
|
155
|
+
body,
|
|
156
|
+
failedResponseHandler: googleFailedResponseHandler,
|
|
157
|
+
successfulResponseHandler: createJsonResponseHandler(
|
|
158
|
+
googleImageResponseSchema,
|
|
159
|
+
),
|
|
160
|
+
abortSignal,
|
|
161
|
+
fetch: this.config.fetch,
|
|
162
|
+
});
|
|
163
|
+
return {
|
|
164
|
+
images: response.predictions.map(
|
|
165
|
+
(p: { bytesBase64Encoded: string }) => p.bytesBase64Encoded,
|
|
166
|
+
),
|
|
167
|
+
warnings,
|
|
168
|
+
providerMetadata: {
|
|
169
|
+
google: {
|
|
170
|
+
images: response.predictions.map(() => ({
|
|
171
|
+
// Add any prediction-specific metadata here
|
|
172
|
+
})),
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
response: {
|
|
176
|
+
timestamp: currentDate,
|
|
177
|
+
modelId: this.modelId,
|
|
178
|
+
headers: responseHeaders,
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private async doGenerateGemini(
|
|
184
|
+
options: Parameters<ImageModelV3['doGenerate']>[0],
|
|
185
|
+
): Promise<Awaited<ReturnType<ImageModelV3['doGenerate']>>> {
|
|
186
|
+
const {
|
|
187
|
+
prompt,
|
|
188
|
+
n,
|
|
189
|
+
size,
|
|
190
|
+
aspectRatio,
|
|
191
|
+
seed,
|
|
192
|
+
providerOptions,
|
|
193
|
+
headers,
|
|
194
|
+
abortSignal,
|
|
195
|
+
files,
|
|
196
|
+
mask,
|
|
197
|
+
} = options;
|
|
198
|
+
const warnings: Array<SharedV3Warning> = [];
|
|
199
|
+
|
|
200
|
+
// Gemini does not support mask-based inpainting
|
|
201
|
+
if (mask != null) {
|
|
202
|
+
throw new Error(
|
|
203
|
+
'Gemini image models do not support mask-based image editing.',
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Gemini does not support generating multiple images per call via n parameter
|
|
208
|
+
if (n != null && n > 1) {
|
|
209
|
+
throw new Error(
|
|
210
|
+
'Gemini image models do not support generating a set number of images per call. Use n=1 or omit the n parameter.',
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (size != null) {
|
|
215
|
+
warnings.push({
|
|
216
|
+
type: 'unsupported',
|
|
217
|
+
feature: 'size',
|
|
218
|
+
details:
|
|
219
|
+
'This model does not support the `size` option. Use `aspectRatio` instead.',
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Build user message content for language model
|
|
224
|
+
const userContent: Array<
|
|
225
|
+
| { type: 'text'; text: string }
|
|
226
|
+
| { type: 'file'; data: string | Uint8Array | URL; mediaType: string }
|
|
227
|
+
> = [];
|
|
228
|
+
|
|
229
|
+
// Add text prompt
|
|
230
|
+
if (prompt != null) {
|
|
231
|
+
userContent.push({ type: 'text', text: prompt });
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Add input images for editing
|
|
235
|
+
if (files != null && files.length > 0) {
|
|
236
|
+
for (const file of files) {
|
|
237
|
+
if (file.type === 'url') {
|
|
238
|
+
userContent.push({
|
|
239
|
+
type: 'file',
|
|
240
|
+
data: new URL(file.url),
|
|
241
|
+
mediaType: 'image/*',
|
|
242
|
+
});
|
|
243
|
+
} else {
|
|
244
|
+
userContent.push({
|
|
245
|
+
type: 'file',
|
|
246
|
+
data:
|
|
247
|
+
typeof file.data === 'string'
|
|
248
|
+
? file.data
|
|
249
|
+
: new Uint8Array(file.data),
|
|
250
|
+
mediaType: file.mediaType,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const languageModelPrompt: LanguageModelV3Prompt = [
|
|
257
|
+
{ role: 'user', content: userContent },
|
|
258
|
+
];
|
|
259
|
+
|
|
260
|
+
// Instantiate language model
|
|
261
|
+
const languageModel = new GoogleGenerativeAILanguageModel(this.modelId, {
|
|
262
|
+
provider: this.config.provider,
|
|
263
|
+
baseURL: this.config.baseURL,
|
|
264
|
+
headers: this.config.headers ?? {},
|
|
265
|
+
fetch: this.config.fetch,
|
|
266
|
+
generateId: this.config.generateId ?? defaultGenerateId,
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// Call language model with image-only response modality
|
|
270
|
+
const result = await languageModel.doGenerate({
|
|
271
|
+
prompt: languageModelPrompt,
|
|
272
|
+
seed,
|
|
273
|
+
providerOptions: {
|
|
274
|
+
google: {
|
|
275
|
+
responseModalities: ['IMAGE'],
|
|
276
|
+
imageConfig: aspectRatio
|
|
277
|
+
? {
|
|
278
|
+
aspectRatio: aspectRatio as NonNullable<
|
|
279
|
+
GoogleLanguageModelOptions['imageConfig']
|
|
280
|
+
>['aspectRatio'],
|
|
281
|
+
}
|
|
282
|
+
: undefined,
|
|
283
|
+
...((providerOptions?.google as Omit<
|
|
284
|
+
GoogleLanguageModelOptions,
|
|
285
|
+
'responseModalities' | 'imageConfig'
|
|
286
|
+
>) ?? {}),
|
|
287
|
+
} satisfies GoogleLanguageModelOptions,
|
|
288
|
+
},
|
|
289
|
+
headers,
|
|
290
|
+
abortSignal,
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
294
|
+
|
|
295
|
+
// Extract images from language model response
|
|
296
|
+
const images: string[] = [];
|
|
297
|
+
for (const part of result.content) {
|
|
298
|
+
if (part.type === 'file' && part.mediaType.startsWith('image/')) {
|
|
299
|
+
images.push(convertToBase64(part.data));
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return {
|
|
304
|
+
images,
|
|
305
|
+
warnings,
|
|
306
|
+
providerMetadata: {
|
|
307
|
+
google: {
|
|
308
|
+
images: images.map(() => ({})),
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
response: {
|
|
312
|
+
timestamp: currentDate,
|
|
313
|
+
modelId: this.modelId,
|
|
314
|
+
headers: result.response?.headers,
|
|
315
|
+
},
|
|
316
|
+
usage: result.usage
|
|
317
|
+
? {
|
|
318
|
+
inputTokens: result.usage.inputTokens.total,
|
|
319
|
+
outputTokens: result.usage.outputTokens.total,
|
|
320
|
+
totalTokens:
|
|
321
|
+
(result.usage.inputTokens.total ?? 0) +
|
|
322
|
+
(result.usage.outputTokens.total ?? 0),
|
|
323
|
+
}
|
|
324
|
+
: undefined,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function isGeminiModel(modelId: string): boolean {
|
|
330
|
+
return modelId.startsWith('gemini-');
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// minimal version of the schema
|
|
334
|
+
const googleImageResponseSchema = lazySchema(() =>
|
|
335
|
+
zodSchema(
|
|
336
|
+
z.object({
|
|
337
|
+
predictions: z
|
|
338
|
+
.array(z.object({ bytesBase64Encoded: z.string() }))
|
|
339
|
+
.default([]),
|
|
340
|
+
}),
|
|
341
|
+
),
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
// Note: For the initial GA launch of Imagen 3, safety filters are not configurable.
|
|
345
|
+
// https://ai.google.dev/gemini-api/docs/imagen#imagen-model
|
|
346
|
+
const googleImageModelOptionsSchema = lazySchema(() =>
|
|
347
|
+
zodSchema(
|
|
348
|
+
z.object({
|
|
349
|
+
personGeneration: z
|
|
350
|
+
.enum(['dont_allow', 'allow_adult', 'allow_all'])
|
|
351
|
+
.nullish(),
|
|
352
|
+
aspectRatio: z.enum(['1:1', '3:4', '4:3', '9:16', '16:9']).nullish(),
|
|
353
|
+
}),
|
|
354
|
+
),
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
export type GoogleImageModelOptions = InferSchema<
|
|
358
|
+
typeof googleImageModelOptionsSchema
|
|
359
|
+
>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type GoogleGenerativeAIImageModelId =
|
|
2
|
+
// Imagen models (use :predict API)
|
|
3
|
+
| 'imagen-4.0-generate-001'
|
|
4
|
+
| 'imagen-4.0-ultra-generate-001'
|
|
5
|
+
| 'imagen-4.0-fast-generate-001'
|
|
6
|
+
// Gemini image models (technically multimodal output language models, use :generateContent API)
|
|
7
|
+
| 'gemini-2.5-flash-image'
|
|
8
|
+
| 'gemini-3-pro-image-preview'
|
|
9
|
+
| 'gemini-3.1-flash-image-preview'
|
|
10
|
+
| (string & {});
|
|
11
|
+
|
|
12
|
+
export interface GoogleGenerativeAIImageSettings {
|
|
13
|
+
/**
|
|
14
|
+
* Override the maximum number of images per call (default 4)
|
|
15
|
+
*/
|
|
16
|
+
maxImagesPerCall?: number;
|
|
17
|
+
}
|