@ai-sdk/google-vertex 4.0.189 → 4.0.191
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 +19 -0
- package/dist/anthropic/edge/index.js +1 -1
- package/dist/anthropic/edge/index.mjs +1 -1
- package/dist/edge/index.js +280 -68
- package/dist/edge/index.js.map +1 -1
- package/dist/edge/index.mjs +266 -45
- package/dist/edge/index.mjs.map +1 -1
- package/dist/index.d.mts +47 -4
- package/dist/index.d.ts +47 -4
- package/dist/index.js +380 -166
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +377 -155
- package/dist/index.mjs.map +1 -1
- package/dist/maas/edge/index.js +1 -1
- package/dist/maas/edge/index.mjs +1 -1
- package/dist/xai/edge/index.js +1 -1
- package/dist/xai/edge/index.mjs +1 -1
- package/package.json +5 -5
- package/src/gemini-transcription/google-vertex-gemini-transcription-model-options.ts +51 -0
- package/src/gemini-transcription/google-vertex-gemini-transcription-model.ts +253 -0
- package/src/google-vertex-provider.ts +14 -0
- package/src/index.ts +5 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InvalidArgumentError,
|
|
3
|
+
type JSONObject,
|
|
4
|
+
type SharedV3Warning,
|
|
5
|
+
type TranscriptionModelV3,
|
|
6
|
+
} from '@ai-sdk/provider';
|
|
7
|
+
import {
|
|
8
|
+
combineHeaders,
|
|
9
|
+
convertToBase64,
|
|
10
|
+
createJsonResponseHandler,
|
|
11
|
+
parseProviderOptions,
|
|
12
|
+
postJsonToApi,
|
|
13
|
+
resolve,
|
|
14
|
+
type FetchFunction,
|
|
15
|
+
type Resolvable,
|
|
16
|
+
} from '@ai-sdk/provider-utils';
|
|
17
|
+
import { z } from 'zod/v4';
|
|
18
|
+
import { googleVertexFailedResponseHandler } from '../google-vertex-error';
|
|
19
|
+
import {
|
|
20
|
+
googleVertexGeminiTranscriptionModelOptions,
|
|
21
|
+
type GoogleVertexGeminiTranscriptionModelId,
|
|
22
|
+
type GoogleVertexTranscriptionModelGeminiOptions,
|
|
23
|
+
} from './google-vertex-gemini-transcription-model-options';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Live transcription (`*-live` model variants) requires streaming support,
|
|
27
|
+
* which is only available in AI SDK v7 (transcription specification v4).
|
|
28
|
+
*/
|
|
29
|
+
function isLiveTranscriptionModelId(modelId: string): boolean {
|
|
30
|
+
return modelId.includes('-live');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface GoogleVertexGeminiTranscriptionModelConfig {
|
|
34
|
+
provider: string;
|
|
35
|
+
/** Regional base URL ending in `/publishers/google`. */
|
|
36
|
+
baseURL: string;
|
|
37
|
+
headers?: Resolvable<Record<string, string | undefined>>;
|
|
38
|
+
fetch?: FetchFunction;
|
|
39
|
+
_internal?: {
|
|
40
|
+
currentDate?: () => Date;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Gemini transcription on Vertex AI (e.g. `gemini-3.5-transcribe`) via
|
|
46
|
+
* `generateContent` with `generationConfig.audioTranscriptionConfig`.
|
|
47
|
+
*/
|
|
48
|
+
export class GoogleVertexGeminiTranscriptionModel implements TranscriptionModelV3 {
|
|
49
|
+
readonly specificationVersion = 'v3';
|
|
50
|
+
|
|
51
|
+
get provider(): string {
|
|
52
|
+
return this.config.provider;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
constructor(
|
|
56
|
+
readonly modelId: GoogleVertexGeminiTranscriptionModelId,
|
|
57
|
+
private readonly config: GoogleVertexGeminiTranscriptionModelConfig,
|
|
58
|
+
) {}
|
|
59
|
+
|
|
60
|
+
private async parseOptions(
|
|
61
|
+
providerOptions: Record<string, unknown> | undefined,
|
|
62
|
+
): Promise<GoogleVertexTranscriptionModelGeminiOptions | undefined> {
|
|
63
|
+
// The Vertex provider exposes options under `googleVertex`/`vertex`;
|
|
64
|
+
// accept `google` as a cross-namespace fallback (e.g. via the AI Gateway).
|
|
65
|
+
for (const provider of ['googleVertex', 'vertex', 'google'] as const) {
|
|
66
|
+
const parsed = await parseProviderOptions({
|
|
67
|
+
provider,
|
|
68
|
+
providerOptions,
|
|
69
|
+
schema: googleVertexGeminiTranscriptionModelOptions,
|
|
70
|
+
});
|
|
71
|
+
if (parsed != null) return parsed;
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async doGenerate(
|
|
77
|
+
options: Parameters<TranscriptionModelV3['doGenerate']>[0],
|
|
78
|
+
): Promise<Awaited<ReturnType<TranscriptionModelV3['doGenerate']>>> {
|
|
79
|
+
if (isLiveTranscriptionModelId(this.modelId)) {
|
|
80
|
+
throw new InvalidArgumentError({
|
|
81
|
+
argument: 'modelId',
|
|
82
|
+
message:
|
|
83
|
+
`Model '${this.modelId}' only supports streaming transcription, ` +
|
|
84
|
+
`which requires AI SDK v7. Use a unary model such as 'gemini-3.5-transcribe'.`,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
89
|
+
const warnings: SharedV3Warning[] = [];
|
|
90
|
+
const googleOptions = await this.parseOptions(options.providerOptions);
|
|
91
|
+
const audioTranscriptionConfig =
|
|
92
|
+
buildAudioTranscriptionConfig(googleOptions);
|
|
93
|
+
|
|
94
|
+
const requestBody = {
|
|
95
|
+
contents: [
|
|
96
|
+
{
|
|
97
|
+
role: 'user',
|
|
98
|
+
parts: [
|
|
99
|
+
{
|
|
100
|
+
inlineData: {
|
|
101
|
+
mimeType: options.mediaType,
|
|
102
|
+
data: convertToBase64(options.audio),
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
...(audioTranscriptionConfig != null
|
|
109
|
+
? { generationConfig: { audioTranscriptionConfig } }
|
|
110
|
+
: {}),
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const {
|
|
114
|
+
value: response,
|
|
115
|
+
responseHeaders,
|
|
116
|
+
rawValue: rawResponse,
|
|
117
|
+
} = await postJsonToApi({
|
|
118
|
+
url: `${this.config.baseURL}/models/${this.modelId}:generateContent`,
|
|
119
|
+
headers: combineHeaders(
|
|
120
|
+
this.config.headers ? await resolve(this.config.headers) : undefined,
|
|
121
|
+
options.headers,
|
|
122
|
+
),
|
|
123
|
+
body: requestBody,
|
|
124
|
+
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
125
|
+
successfulResponseHandler: createJsonResponseHandler(
|
|
126
|
+
googleVertexGeminiTranscriptionResponseSchema,
|
|
127
|
+
),
|
|
128
|
+
abortSignal: options.abortSignal,
|
|
129
|
+
fetch: this.config.fetch,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const parts = response.candidates?.[0]?.content?.parts ?? [];
|
|
133
|
+
const plainText = parts.map(part => part.text ?? '').join('');
|
|
134
|
+
const transcriptionText = parts
|
|
135
|
+
.map(part => part.audioTranscription?.text ?? '')
|
|
136
|
+
.join('');
|
|
137
|
+
const text = plainText !== '' ? plainText : transcriptionText;
|
|
138
|
+
|
|
139
|
+
let language: string | undefined;
|
|
140
|
+
const segments: Array<{
|
|
141
|
+
text: string;
|
|
142
|
+
startSecond: number;
|
|
143
|
+
endSecond: number;
|
|
144
|
+
}> = [];
|
|
145
|
+
for (const part of parts) {
|
|
146
|
+
const transcription = part.audioTranscription;
|
|
147
|
+
if (transcription == null) continue;
|
|
148
|
+
language ??= transcription.languageCode ?? undefined;
|
|
149
|
+
for (const word of transcription.words ?? []) {
|
|
150
|
+
const startSecond = parseOffsetSeconds(word.startOffset);
|
|
151
|
+
const endSecond = parseOffsetSeconds(word.endOffset);
|
|
152
|
+
if (word.word == null || startSecond == null || endSecond == null) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
segments.push({ text: word.word, startSecond, endSecond });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
text,
|
|
161
|
+
segments,
|
|
162
|
+
language,
|
|
163
|
+
durationInSeconds: undefined,
|
|
164
|
+
warnings,
|
|
165
|
+
response: {
|
|
166
|
+
timestamp: currentDate,
|
|
167
|
+
modelId: this.modelId,
|
|
168
|
+
headers: responseHeaders,
|
|
169
|
+
body: rawResponse,
|
|
170
|
+
},
|
|
171
|
+
...(response.usageMetadata != null
|
|
172
|
+
? {
|
|
173
|
+
providerMetadata: {
|
|
174
|
+
google: { usageMetadata: response.usageMetadata as JSONObject },
|
|
175
|
+
},
|
|
176
|
+
}
|
|
177
|
+
: {}),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Builds Google's `AudioTranscriptionConfig` from provider options; returns
|
|
184
|
+
* undefined when no options are set.
|
|
185
|
+
*/
|
|
186
|
+
function buildAudioTranscriptionConfig(
|
|
187
|
+
options: GoogleVertexTranscriptionModelGeminiOptions | undefined,
|
|
188
|
+
): Record<string, unknown> | undefined {
|
|
189
|
+
if (options == null) return undefined;
|
|
190
|
+
const config: Record<string, unknown> = {};
|
|
191
|
+
if (options.languageCodes != null) {
|
|
192
|
+
config.languageCodes = options.languageCodes;
|
|
193
|
+
}
|
|
194
|
+
if (options.customVocabulary != null) {
|
|
195
|
+
config.customVocabulary = options.customVocabulary;
|
|
196
|
+
}
|
|
197
|
+
if (options.wordTimestamp != null) {
|
|
198
|
+
config.wordTimestamp = options.wordTimestamp;
|
|
199
|
+
}
|
|
200
|
+
if (options.diarization != null) {
|
|
201
|
+
config.diarization = options.diarization;
|
|
202
|
+
}
|
|
203
|
+
if (options.mode != null) {
|
|
204
|
+
config.mode = options.mode;
|
|
205
|
+
}
|
|
206
|
+
return Object.keys(config).length > 0 ? config : undefined;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** Parses a Google duration offset such as `"1s"` or `"9.400s"` to seconds. */
|
|
210
|
+
function parseOffsetSeconds(
|
|
211
|
+
offset: string | undefined | null,
|
|
212
|
+
): number | undefined {
|
|
213
|
+
if (offset == null) return undefined;
|
|
214
|
+
const parsed = Number.parseFloat(offset);
|
|
215
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const googleVertexGeminiTranscriptionWordSchema = z.object({
|
|
219
|
+
word: z.string().nullish(),
|
|
220
|
+
startOffset: z.string().nullish(),
|
|
221
|
+
endOffset: z.string().nullish(),
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const googleVertexGeminiTranscriptionResponseSchema = z.object({
|
|
225
|
+
candidates: z
|
|
226
|
+
.array(
|
|
227
|
+
z.object({
|
|
228
|
+
content: z
|
|
229
|
+
.object({
|
|
230
|
+
parts: z
|
|
231
|
+
.array(
|
|
232
|
+
z.object({
|
|
233
|
+
text: z.string().nullish(),
|
|
234
|
+
audioTranscription: z
|
|
235
|
+
.object({
|
|
236
|
+
text: z.string().nullish(),
|
|
237
|
+
languageCode: z.string().nullish(),
|
|
238
|
+
speakerLabel: z.string().nullish(),
|
|
239
|
+
words: z
|
|
240
|
+
.array(googleVertexGeminiTranscriptionWordSchema)
|
|
241
|
+
.nullish(),
|
|
242
|
+
})
|
|
243
|
+
.nullish(),
|
|
244
|
+
}),
|
|
245
|
+
)
|
|
246
|
+
.nullish(),
|
|
247
|
+
})
|
|
248
|
+
.nullish(),
|
|
249
|
+
}),
|
|
250
|
+
)
|
|
251
|
+
.nullish(),
|
|
252
|
+
usageMetadata: z.record(z.string(), z.unknown()).nullish(),
|
|
253
|
+
});
|
|
@@ -33,6 +33,7 @@ import type { GoogleVertexModelId } from './google-vertex-options';
|
|
|
33
33
|
import { googleVertexTools } from './google-vertex-tools';
|
|
34
34
|
import { GoogleVertexTranscriptionModel } from './google-vertex-transcription-model';
|
|
35
35
|
import type { GoogleVertexTranscriptionModelId } from './google-vertex-transcription-model-options';
|
|
36
|
+
import { GoogleVertexGeminiTranscriptionModel } from './gemini-transcription/google-vertex-gemini-transcription-model';
|
|
36
37
|
import { GoogleVertexVideoModel } from './google-vertex-video-model';
|
|
37
38
|
import type { GoogleVertexVideoModelId } from './google-vertex-video-settings';
|
|
38
39
|
|
|
@@ -305,6 +306,19 @@ export function createVertex(
|
|
|
305
306
|
}
|
|
306
307
|
|
|
307
308
|
const config = createConfig('transcription');
|
|
309
|
+
|
|
310
|
+
// Gemini transcription models (`gemini-3.5-transcribe`) use the Vertex
|
|
311
|
+
// generateContent surface; everything else routes to Cloud
|
|
312
|
+
// Speech-to-Text (Chirp, telephony).
|
|
313
|
+
if (modelId.startsWith('gemini')) {
|
|
314
|
+
return new GoogleVertexGeminiTranscriptionModel(modelId, {
|
|
315
|
+
provider: config.provider,
|
|
316
|
+
baseURL: loadBaseURL(),
|
|
317
|
+
headers: config.headers,
|
|
318
|
+
fetch: config.fetch,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
308
322
|
return new GoogleVertexTranscriptionModel(modelId, {
|
|
309
323
|
provider: config.provider,
|
|
310
324
|
headers: config.headers,
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,11 @@ export type {
|
|
|
14
14
|
GoogleVertexVideoModelOptions as GoogleVertexVideoProviderOptions,
|
|
15
15
|
} from './google-vertex-video-model';
|
|
16
16
|
export type { GoogleVertexVideoModelId } from './google-vertex-video-settings';
|
|
17
|
+
export { GoogleVertexGeminiTranscriptionModel } from './gemini-transcription/google-vertex-gemini-transcription-model';
|
|
18
|
+
export type {
|
|
19
|
+
GoogleVertexGeminiTranscriptionModelId,
|
|
20
|
+
GoogleVertexTranscriptionModelGeminiOptions,
|
|
21
|
+
} from './gemini-transcription/google-vertex-gemini-transcription-model-options';
|
|
17
22
|
export { createVertex, vertex } from './google-vertex-provider-node';
|
|
18
23
|
export type {
|
|
19
24
|
GoogleVertexProvider,
|