@ai-sdk/google 3.0.49 → 3.0.50

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.
@@ -1131,6 +1131,28 @@ const { embedding } = await embed({
1131
1131
  google: {
1132
1132
  outputDimensionality: 512, // optional, number of dimensions for the embedding
1133
1133
  taskType: 'SEMANTIC_SIMILARITY', // optional, specifies the task type for generating embeddings
1134
+ content: [[{ text: 'additional context' }]], // optional, per-value multimodal content (only 1 here, since `value` is only a single one)
1135
+ } satisfies GoogleEmbeddingModelOptions,
1136
+ },
1137
+ });
1138
+ ```
1139
+
1140
+ When using `embedMany`, provide per-value multimodal content via the `content` option. Each entry corresponds to a value at the same index; use `null` for text-only entries:
1141
+
1142
+ ```ts
1143
+ import { google, type GoogleEmbeddingModelOptions } from '@ai-sdk/google';
1144
+ import { embedMany } from 'ai';
1145
+
1146
+ const { embeddings } = await embedMany({
1147
+ model: google.embedding('gemini-embedding-2-preview'),
1148
+ values: ['sunny day at the beach', 'rainy afternoon in the city'],
1149
+ providerOptions: {
1150
+ google: {
1151
+ // content array must have the same length as values
1152
+ content: [
1153
+ [{ inlineData: { mimeType: 'image/png', data: '<base64>' } }], // pairs with values[0]
1154
+ null, // text-only, pairs with values[1]
1155
+ ],
1134
1156
  } satisfies GoogleEmbeddingModelOptions,
1135
1157
  },
1136
1158
  });
@@ -1155,11 +1177,16 @@ The following optional provider options are available for Google Generative AI e
1155
1177
  - `FACT_VERIFICATION`: Optimized for verifying factual information.
1156
1178
  - `CODE_RETRIEVAL_QUERY`: Optimized for retrieving code blocks based on natural language queries.
1157
1179
 
1180
+ - **content**: _array_
1181
+
1182
+ Optional. Per-value multimodal content parts for embedding non-text content (images, video, PDF, audio). Each entry corresponds to the embedding value at the same index — its parts are merged with the text value in the request. Use `null` for entries that are text-only. The array length must match the number of values being embedded. Each non-null entry is an array of parts, where each part can be either `{ text: string }` or `{ inlineData: { mimeType: string, data: string } }`. Supported by `gemini-embedding-2-preview`.
1183
+
1158
1184
  ### Model Capabilities
1159
1185
 
1160
- | Model | Default Dimensions | Custom Dimensions |
1161
- | ---------------------- | ------------------ | ------------------- |
1162
- | `gemini-embedding-001` | 3072 | <Check size={18} /> |
1186
+ | Model | Default Dimensions | Custom Dimensions | Multimodal |
1187
+ | ---------------------------- | ------------------ | ------------------- | ------------------- |
1188
+ | `gemini-embedding-001` | 3072 | <Check size={18} /> | <Cross size={18} /> |
1189
+ | `gemini-embedding-2-preview` | 3072 | <Check size={18} /> | <Check size={18} /> |
1163
1190
 
1164
1191
  ## Image Models
1165
1192
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/google",
3
- "version": "3.0.49",
3
+ "version": "3.0.50",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -36,16 +36,16 @@
36
36
  }
37
37
  },
38
38
  "dependencies": {
39
- "@ai-sdk/provider-utils": "4.0.20",
40
- "@ai-sdk/provider": "3.0.8"
39
+ "@ai-sdk/provider": "3.0.8",
40
+ "@ai-sdk/provider-utils": "4.0.20"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "20.17.24",
44
44
  "tsup": "^8",
45
45
  "typescript": "5.8.3",
46
46
  "zod": "3.25.76",
47
- "@vercel/ai-tsconfig": "0.0.0",
48
- "@ai-sdk/test-server": "1.0.3"
47
+ "@ai-sdk/test-server": "1.0.3",
48
+ "@vercel/ai-tsconfig": "0.0.0"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "zod": "^3.25.76 || ^4.1.8"
@@ -74,14 +74,24 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
74
74
  headers,
75
75
  );
76
76
 
77
- const multimodalContent = googleOptions?.content ?? [];
77
+ const multimodalContent = googleOptions?.content;
78
+
79
+ if (
80
+ multimodalContent != null &&
81
+ multimodalContent.length !== values.length
82
+ ) {
83
+ throw new Error(
84
+ `The number of multimodal content entries (${multimodalContent.length}) must match the number of values (${values.length}).`,
85
+ );
86
+ }
78
87
 
79
88
  // For single embeddings, use the single endpoint
80
89
  if (values.length === 1) {
90
+ const valueParts = multimodalContent?.[0];
81
91
  const textPart = values[0] ? [{ text: values[0] }] : [];
82
92
  const parts =
83
- multimodalContent.length > 0
84
- ? [...textPart, ...multimodalContent]
93
+ valueParts != null
94
+ ? [...textPart, ...valueParts]
85
95
  : [{ text: values[0] }];
86
96
 
87
97
  const {
@@ -116,7 +126,6 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
116
126
  }
117
127
 
118
128
  // For multiple values, use the batch endpoint
119
- // If multimodal content is provided, merge it into each request's parts
120
129
  const {
121
130
  responseHeaders,
122
131
  value: response,
@@ -125,15 +134,16 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
125
134
  url: `${this.config.baseURL}/models/${this.modelId}:batchEmbedContents`,
126
135
  headers: mergedHeaders,
127
136
  body: {
128
- requests: values.map(value => {
137
+ requests: values.map((value, index) => {
138
+ const valueParts = multimodalContent?.[index];
129
139
  const textPart = value ? [{ text: value }] : [];
130
140
  return {
131
141
  model: `models/${this.modelId}`,
132
142
  content: {
133
143
  role: 'user',
134
144
  parts:
135
- multimodalContent.length > 0
136
- ? [...textPart, ...multimodalContent]
145
+ valueParts != null
146
+ ? [...textPart, ...valueParts]
137
147
  : [{ text: value }],
138
148
  },
139
149
  outputDimensionality: googleOptions?.outputDimensionality,
@@ -7,6 +7,7 @@ import { z } from 'zod/v4';
7
7
 
8
8
  export type GoogleGenerativeAIEmbeddingModelId =
9
9
  | 'gemini-embedding-001'
10
+ | 'gemini-embedding-2-preview'
10
11
  | (string & {});
11
12
 
12
13
  const googleEmbeddingContentPartSchema = z.union([
@@ -54,11 +55,17 @@ export const googleEmbeddingModelOptions = lazySchema(() =>
54
55
  .optional(),
55
56
 
56
57
  /**
57
- * Optional. Multimodal content parts for embedding non-text content
58
- * (images, video, PDF, audio). When provided, these parts are merged
59
- * with the text values in the embedding request.
58
+ * Optional. Per-value multimodal content parts for embedding non-text
59
+ * content (images, video, PDF, audio). Each entry corresponds to the
60
+ * embedding value at the same index and its parts are merged with the
61
+ * text value in the request. Use `null` for entries that are text-only.
62
+ *
63
+ * The array length must match the number of values being embedded. In
64
+ * the case of a single embedding, the array length must be 1.
60
65
  */
61
- content: z.array(googleEmbeddingContentPartSchema).min(1).optional(),
66
+ content: z
67
+ .array(z.array(googleEmbeddingContentPartSchema).min(1).nullable())
68
+ .optional(),
62
69
  }),
63
70
  ),
64
71
  );