@ai-sdk/google-vertex 5.0.49 → 5.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.
- package/CHANGELOG.md +9 -0
- package/dist/anthropic/edge/index.js +1 -1
- package/dist/edge/index.d.ts +1 -1
- package/dist/edge/index.js +216 -80
- package/dist/edge/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +216 -80
- package/dist/index.js.map +1 -1
- package/dist/maas/edge/index.js +1 -1
- package/dist/xai/edge/index.js +1 -1
- package/package.json +2 -2
- package/src/google-vertex-cloud-tts-speech-model.ts +188 -0
- package/src/google-vertex-provider-base.ts +19 -2
- package/src/google-vertex-speech-model-options.ts +4 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { SharedV4Warning, SpeechModelV4 } from '@ai-sdk/provider';
|
|
2
|
+
import {
|
|
3
|
+
combineHeaders,
|
|
4
|
+
convertBase64ToUint8Array,
|
|
5
|
+
createJsonResponseHandler,
|
|
6
|
+
postJsonToApi,
|
|
7
|
+
resolve,
|
|
8
|
+
serializeModelOptions,
|
|
9
|
+
WORKFLOW_DESERIALIZE,
|
|
10
|
+
WORKFLOW_SERIALIZE,
|
|
11
|
+
type FetchFunction,
|
|
12
|
+
type Resolvable,
|
|
13
|
+
} from '@ai-sdk/provider-utils';
|
|
14
|
+
import { z } from 'zod/v4';
|
|
15
|
+
import { googleVertexFailedResponseHandler } from './google-vertex-error';
|
|
16
|
+
import type { GoogleVertexSpeechModelId } from './google-vertex-speech-model-options';
|
|
17
|
+
|
|
18
|
+
interface GoogleVertexCloudTTSSpeechModelConfig {
|
|
19
|
+
provider: string;
|
|
20
|
+
headers?: Resolvable<Record<string, string | undefined>>;
|
|
21
|
+
fetch?: FetchFunction;
|
|
22
|
+
_internal?: {
|
|
23
|
+
currentDate?: () => Date;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const DEFAULT_VOICE = 'Kore';
|
|
28
|
+
const DEFAULT_LANGUAGE = 'en-US';
|
|
29
|
+
|
|
30
|
+
// Chirp 3: HD voice names are `<locale>-Chirp3-HD-<voice>`,
|
|
31
|
+
// e.g. `en-US-Chirp3-HD-Kore`.
|
|
32
|
+
// https://cloud.google.com/text-to-speech/docs/chirp3-hd
|
|
33
|
+
const CHIRP3_HD_VOICE_INFIX = 'Chirp3-HD';
|
|
34
|
+
|
|
35
|
+
// Cloud Text-to-Speech uses a single non-regional host for standard
|
|
36
|
+
// synthesis (unlike Speech-to-Text and Vertex AI, which are regional).
|
|
37
|
+
// https://cloud.google.com/text-to-speech/docs/reference/rest/v1/text/synthesize
|
|
38
|
+
const CLOUD_TTS_SYNTHESIZE_URL =
|
|
39
|
+
'https://texttospeech.googleapis.com/v1/text:synthesize';
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Speech model for Chirp 3: HD voices on the Google Cloud Text-to-Speech API.
|
|
43
|
+
*
|
|
44
|
+
* Unlike the Gemini TTS models (which go through the Vertex
|
|
45
|
+
* `generateContent` endpoint via `GoogleSpeechModel`), Chirp 3: HD voices are
|
|
46
|
+
* served by the dedicated Cloud Text-to-Speech `text:synthesize` endpoint,
|
|
47
|
+
* reusing the provider's Google Cloud credentials.
|
|
48
|
+
*/
|
|
49
|
+
export class GoogleVertexCloudTTSSpeechModel implements SpeechModelV4 {
|
|
50
|
+
readonly specificationVersion = 'v4';
|
|
51
|
+
|
|
52
|
+
static [WORKFLOW_SERIALIZE](model: GoogleVertexCloudTTSSpeechModel) {
|
|
53
|
+
return serializeModelOptions({
|
|
54
|
+
modelId: model.modelId,
|
|
55
|
+
config: model.config,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
60
|
+
modelId: GoogleVertexSpeechModelId;
|
|
61
|
+
config: GoogleVertexCloudTTSSpeechModelConfig;
|
|
62
|
+
}) {
|
|
63
|
+
return new GoogleVertexCloudTTSSpeechModel(options.modelId, options.config);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
get provider(): string {
|
|
67
|
+
return this.config.provider;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
constructor(
|
|
71
|
+
readonly modelId: GoogleVertexSpeechModelId,
|
|
72
|
+
private readonly config: GoogleVertexCloudTTSSpeechModelConfig,
|
|
73
|
+
) {}
|
|
74
|
+
|
|
75
|
+
async doGenerate(
|
|
76
|
+
options: Parameters<SpeechModelV4['doGenerate']>[0],
|
|
77
|
+
): Promise<Awaited<ReturnType<SpeechModelV4['doGenerate']>>> {
|
|
78
|
+
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
79
|
+
const warnings: SharedV4Warning[] = [];
|
|
80
|
+
|
|
81
|
+
const {
|
|
82
|
+
text,
|
|
83
|
+
voice = DEFAULT_VOICE,
|
|
84
|
+
outputFormat,
|
|
85
|
+
instructions,
|
|
86
|
+
speed,
|
|
87
|
+
language,
|
|
88
|
+
} = options;
|
|
89
|
+
|
|
90
|
+
// Compose the voice name. A fully-qualified Chirp 3: HD voice name
|
|
91
|
+
// (e.g. `en-US-Chirp3-HD-Kore`) is passed through verbatim, with its
|
|
92
|
+
// locale prefix as the language code; otherwise the name is composed
|
|
93
|
+
// from the language (BCP-47 locale, e.g. `en-US`) and the plain voice
|
|
94
|
+
// name (e.g. `Kore`).
|
|
95
|
+
let voiceName: string;
|
|
96
|
+
let languageCode: string;
|
|
97
|
+
if (voice.includes(CHIRP3_HD_VOICE_INFIX)) {
|
|
98
|
+
voiceName = voice;
|
|
99
|
+
// The locale prefix may be missing (e.g. `Chirp3-HD-Kore`), in which
|
|
100
|
+
// case the extracted prefix is empty and the default language is used.
|
|
101
|
+
const localePrefix = voice
|
|
102
|
+
.split(CHIRP3_HD_VOICE_INFIX)[0]
|
|
103
|
+
.replace(/-$/, '');
|
|
104
|
+
languageCode = language ?? (localePrefix || DEFAULT_LANGUAGE);
|
|
105
|
+
} else {
|
|
106
|
+
languageCode = language ?? DEFAULT_LANGUAGE;
|
|
107
|
+
voiceName = `${languageCode}-${CHIRP3_HD_VOICE_INFIX}-${voice}`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (instructions != null) {
|
|
111
|
+
warnings.push({
|
|
112
|
+
type: 'unsupported',
|
|
113
|
+
feature: 'instructions',
|
|
114
|
+
details:
|
|
115
|
+
'Google Cloud Text-to-Speech Chirp 3: HD voices do not support the `instructions` option. It was ignored.',
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// LINEAR16 responses are WAV (RIFF) files, so only `wav` is supported.
|
|
120
|
+
if (outputFormat != null && outputFormat !== 'wav') {
|
|
121
|
+
warnings.push({
|
|
122
|
+
type: 'unsupported',
|
|
123
|
+
feature: 'outputFormat',
|
|
124
|
+
details: `Unsupported output format: ${outputFormat}. Using wav instead.`,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const requestBody = {
|
|
129
|
+
input: { text },
|
|
130
|
+
voice: { languageCode, name: voiceName },
|
|
131
|
+
audioConfig: {
|
|
132
|
+
audioEncoding: 'LINEAR16',
|
|
133
|
+
...(speed != null ? { speakingRate: speed } : {}),
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const {
|
|
138
|
+
value: response,
|
|
139
|
+
responseHeaders,
|
|
140
|
+
rawValue: rawResponse,
|
|
141
|
+
} = await postJsonToApi({
|
|
142
|
+
url: CLOUD_TTS_SYNTHESIZE_URL,
|
|
143
|
+
headers: combineHeaders(
|
|
144
|
+
this.config.headers ? await resolve(this.config.headers) : undefined,
|
|
145
|
+
options.headers,
|
|
146
|
+
),
|
|
147
|
+
body: requestBody,
|
|
148
|
+
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
149
|
+
successfulResponseHandler: createJsonResponseHandler(
|
|
150
|
+
googleVertexCloudTTSResponseSchema,
|
|
151
|
+
),
|
|
152
|
+
abortSignal: options.abortSignal,
|
|
153
|
+
fetch: this.config.fetch,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Empty audio is returned as-is so the core layer throws
|
|
157
|
+
// NoSpeechGeneratedError.
|
|
158
|
+
const audio =
|
|
159
|
+
response.audioContent != null
|
|
160
|
+
? convertBase64ToUint8Array(response.audioContent)
|
|
161
|
+
: new Uint8Array(0);
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
audio,
|
|
165
|
+
warnings,
|
|
166
|
+
request: {
|
|
167
|
+
body: JSON.stringify(requestBody),
|
|
168
|
+
},
|
|
169
|
+
response: {
|
|
170
|
+
timestamp: currentDate,
|
|
171
|
+
modelId: this.modelId,
|
|
172
|
+
headers: responseHeaders,
|
|
173
|
+
body: rawResponse,
|
|
174
|
+
},
|
|
175
|
+
providerMetadata: {
|
|
176
|
+
google: {
|
|
177
|
+
mimeType: 'audio/wav',
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Minimal schema: only the fields the implementation reads, with `.nullish()`
|
|
185
|
+
// so provider API changes don't break parsing.
|
|
186
|
+
const googleVertexCloudTTSResponseSchema = z.object({
|
|
187
|
+
audioContent: z.string().nullish(),
|
|
188
|
+
});
|
|
@@ -32,6 +32,7 @@ import type { GoogleVertexEmbeddingModelId } from './google-vertex-embedding-mod
|
|
|
32
32
|
import { GoogleVertexImageModel } from './google-vertex-image-model';
|
|
33
33
|
import type { GoogleVertexImageModelId } from './google-vertex-image-settings';
|
|
34
34
|
import type { GoogleVertexModelId } from './google-vertex-options';
|
|
35
|
+
import { GoogleVertexCloudTTSSpeechModel } from './google-vertex-cloud-tts-speech-model';
|
|
35
36
|
import { googleVertexTools } from './google-vertex-tools';
|
|
36
37
|
import { GoogleVertexTranscriptionModel } from './google-vertex-transcription-model';
|
|
37
38
|
import type { GoogleVertexTranscriptionModelId } from './google-vertex-transcription-model-options';
|
|
@@ -327,8 +328,24 @@ export function createGoogleVertex(
|
|
|
327
328
|
generateId: options.generateId ?? generateId,
|
|
328
329
|
});
|
|
329
330
|
|
|
330
|
-
const createSpeechModel = (modelId: GoogleVertexSpeechModelId) =>
|
|
331
|
-
|
|
331
|
+
const createSpeechModel = (modelId: GoogleVertexSpeechModelId) => {
|
|
332
|
+
if (modelId.startsWith('chirp')) {
|
|
333
|
+
if (apiKey) {
|
|
334
|
+
throw new Error(
|
|
335
|
+
'Google Vertex Chirp speech models do not support Express Mode API keys. Use standard Google Cloud credentials instead.',
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const config = createConfig('speech');
|
|
340
|
+
return new GoogleVertexCloudTTSSpeechModel(modelId, {
|
|
341
|
+
provider: config.provider,
|
|
342
|
+
headers: config.headers,
|
|
343
|
+
fetch: config.fetch,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return new GoogleSpeechModel(modelId, createConfig('speech'));
|
|
348
|
+
};
|
|
332
349
|
|
|
333
350
|
// Cloud Speech-to-Text reuses the Vertex auth headers from createConfig, but
|
|
334
351
|
// targets the Speech-to-Text API.
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { GoogleSpeechModelOptions } from '@ai-sdk/google';
|
|
2
2
|
|
|
3
|
+
// Gemini TTS models (Vertex `generateContent` endpoint):
|
|
3
4
|
// https://docs.cloud.google.com/text-to-speech/docs/gemini-tts
|
|
5
|
+
// Chirp 3: HD voices (Cloud Text-to-Speech `text:synthesize` endpoint):
|
|
6
|
+
// https://docs.cloud.google.com/text-to-speech/docs/chirp3-hd
|
|
4
7
|
export type GoogleVertexSpeechModelId =
|
|
5
8
|
| 'gemini-2.5-flash-tts'
|
|
6
9
|
| 'gemini-2.5-pro-tts'
|
|
7
10
|
| 'gemini-2.5-flash-lite-preview-tts'
|
|
8
11
|
| 'gemini-3.1-flash-tts-preview'
|
|
12
|
+
| 'chirp-3-hd'
|
|
9
13
|
| (string & {});
|
|
10
14
|
|
|
11
15
|
export type GoogleVertexSpeechModelOptions = GoogleSpeechModelOptions;
|