@ai-sdk/google-vertex
Version:
The **[Google Vertex provider](https://ai-sdk.dev/providers/ai-sdk-providers/google-vertex)** for the [AI SDK](https://ai-sdk.dev/docs) contains language model support for the [Google Vertex AI](https://cloud.google.com/vertex-ai) APIs.
555 lines (544 loc) • 17.8 kB
JavaScript
// src/google-vertex-provider-node.ts
import { loadOptionalSetting as loadOptionalSetting2, resolve as resolve4 } from "@ai-sdk/provider-utils";
// src/google-vertex-auth-google-auth-library.ts
import { GoogleAuth } from "google-auth-library";
var authInstance = null;
var authOptions = null;
function getAuth(options) {
if (!authInstance || options !== authOptions) {
authInstance = new GoogleAuth({
scopes: ["https://www.googleapis.com/auth/cloud-platform"],
...options
});
authOptions = options;
}
return authInstance;
}
async function generateAuthToken(options) {
const auth = getAuth(options || {});
const client = await auth.getClient();
const token = await client.getAccessToken();
return (token == null ? void 0 : token.token) || null;
}
// src/google-vertex-provider.ts
import { GoogleGenerativeAILanguageModel } from "@ai-sdk/google/internal";
import {
generateId,
loadOptionalSetting,
loadSetting,
normalizeHeaders,
resolve as resolve3,
withoutTrailingSlash,
withUserAgentSuffix
} from "@ai-sdk/provider-utils";
// src/version.ts
var VERSION = true ? "4.0.28" : "0.0.0-test";
// src/google-vertex-embedding-model.ts
import {
TooManyEmbeddingValuesForCallError
} from "@ai-sdk/provider";
import {
combineHeaders,
createJsonResponseHandler,
postJsonToApi,
resolve,
parseProviderOptions
} from "@ai-sdk/provider-utils";
import { z as z3 } from "zod/v4";
// src/google-vertex-error.ts
import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils";
import { z } from "zod/v4";
var googleVertexErrorDataSchema = z.object({
error: z.object({
code: z.number().nullable(),
message: z.string(),
status: z.string()
})
});
var googleVertexFailedResponseHandler = createJsonErrorResponseHandler(
{
errorSchema: googleVertexErrorDataSchema,
errorToMessage: (data) => data.error.message
}
);
// src/google-vertex-embedding-options.ts
import { z as z2 } from "zod/v4";
var googleVertexEmbeddingProviderOptions = z2.object({
/**
* Optional. Optional reduced dimension for the output embedding.
* If set, excessive values in the output embedding are truncated from the end.
*/
outputDimensionality: z2.number().optional(),
/**
* Optional. Specifies the task type for generating embeddings.
* Supported task types:
* - SEMANTIC_SIMILARITY: Optimized for text similarity.
* - CLASSIFICATION: Optimized for text classification.
* - CLUSTERING: Optimized for clustering texts based on similarity.
* - RETRIEVAL_DOCUMENT: Optimized for document retrieval.
* - RETRIEVAL_QUERY: Optimized for query-based retrieval.
* - QUESTION_ANSWERING: Optimized for answering questions.
* - FACT_VERIFICATION: Optimized for verifying factual information.
* - CODE_RETRIEVAL_QUERY: Optimized for retrieving code blocks based on natural language queries.
*/
taskType: z2.enum([
"SEMANTIC_SIMILARITY",
"CLASSIFICATION",
"CLUSTERING",
"RETRIEVAL_DOCUMENT",
"RETRIEVAL_QUERY",
"QUESTION_ANSWERING",
"FACT_VERIFICATION",
"CODE_RETRIEVAL_QUERY"
]).optional(),
/**
* Optional. The title of the document being embedded.
* Only valid when task_type is set to 'RETRIEVAL_DOCUMENT'.
* Helps the model produce better embeddings by providing additional context.
*/
title: z2.string().optional(),
/**
* Optional. When set to true, input text will be truncated. When set to false,
* an error is returned if the input text is longer than the maximum length supported by the model. Defaults to true.
*/
autoTruncate: z2.boolean().optional()
});
// src/google-vertex-embedding-model.ts
var GoogleVertexEmbeddingModel = class {
constructor(modelId, config) {
this.specificationVersion = "v3";
this.maxEmbeddingsPerCall = 2048;
this.supportsParallelCalls = true;
this.modelId = modelId;
this.config = config;
}
get provider() {
return this.config.provider;
}
async doEmbed({
values,
headers,
abortSignal,
providerOptions
}) {
let googleOptions = await parseProviderOptions({
provider: "vertex",
providerOptions,
schema: googleVertexEmbeddingProviderOptions
});
if (googleOptions == null) {
googleOptions = await parseProviderOptions({
provider: "google",
providerOptions,
schema: googleVertexEmbeddingProviderOptions
});
}
googleOptions = googleOptions != null ? googleOptions : {};
if (values.length > this.maxEmbeddingsPerCall) {
throw new TooManyEmbeddingValuesForCallError({
provider: this.provider,
modelId: this.modelId,
maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
values
});
}
const mergedHeaders = combineHeaders(
await resolve(this.config.headers),
headers
);
const url = `${this.config.baseURL}/models/${this.modelId}:predict`;
const {
responseHeaders,
value: response,
rawValue
} = await postJsonToApi({
url,
headers: mergedHeaders,
body: {
instances: values.map((value) => ({
content: value,
task_type: googleOptions.taskType,
title: googleOptions.title
})),
parameters: {
outputDimensionality: googleOptions.outputDimensionality,
autoTruncate: googleOptions.autoTruncate
}
},
failedResponseHandler: googleVertexFailedResponseHandler,
successfulResponseHandler: createJsonResponseHandler(
googleVertexTextEmbeddingResponseSchema
),
abortSignal,
fetch: this.config.fetch
});
return {
warnings: [],
embeddings: response.predictions.map(
(prediction) => prediction.embeddings.values
),
usage: {
tokens: response.predictions.reduce(
(tokenCount, prediction) => tokenCount + prediction.embeddings.statistics.token_count,
0
)
},
response: { headers: responseHeaders, body: rawValue }
};
}
};
var googleVertexTextEmbeddingResponseSchema = z3.object({
predictions: z3.array(
z3.object({
embeddings: z3.object({
values: z3.array(z3.number()),
statistics: z3.object({
token_count: z3.number()
})
})
})
)
});
// src/google-vertex-image-model.ts
import {
combineHeaders as combineHeaders2,
convertUint8ArrayToBase64,
createJsonResponseHandler as createJsonResponseHandler2,
parseProviderOptions as parseProviderOptions2,
postJsonToApi as postJsonToApi2,
resolve as resolve2
} from "@ai-sdk/provider-utils";
import { z as z4 } from "zod/v4";
var GoogleVertexImageModel = class {
constructor(modelId, config) {
this.modelId = modelId;
this.config = config;
this.specificationVersion = "v3";
// https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-api#parameter_list
this.maxImagesPerCall = 4;
}
get provider() {
return this.config.provider;
}
async doGenerate({
prompt,
n,
size,
aspectRatio,
seed,
providerOptions,
headers,
abortSignal,
files,
mask
}) {
var _a, _b, _c, _d, _e, _f, _g;
const warnings = [];
if (size != null) {
warnings.push({
type: "unsupported",
feature: "size",
details: "This model does not support the `size` option. Use `aspectRatio` instead."
});
}
const vertexImageOptions = await parseProviderOptions2({
provider: "vertex",
providerOptions,
schema: vertexImageProviderOptionsSchema
});
const { edit, ...otherOptions } = vertexImageOptions != null ? vertexImageOptions : {};
const { mode: editMode, baseSteps, maskMode, maskDilation } = edit != null ? edit : {};
const isEditMode = files != null && files.length > 0;
let body;
if (isEditMode) {
const referenceImages = [];
for (let i = 0; i < files.length; i++) {
const file = files[i];
referenceImages.push({
referenceType: "REFERENCE_TYPE_RAW",
referenceId: i + 1,
referenceImage: {
bytesBase64Encoded: getBase64Data(file)
}
});
}
if (mask != null) {
referenceImages.push({
referenceType: "REFERENCE_TYPE_MASK",
referenceId: files.length + 1,
referenceImage: {
bytesBase64Encoded: getBase64Data(mask)
},
maskImageConfig: {
maskMode: maskMode != null ? maskMode : "MASK_MODE_USER_PROVIDED",
...maskDilation != null ? { dilation: maskDilation } : {}
}
});
}
body = {
instances: [
{
prompt,
referenceImages
}
],
parameters: {
sampleCount: n,
...aspectRatio != null ? { aspectRatio } : {},
...seed != null ? { seed } : {},
editMode: editMode != null ? editMode : "EDIT_MODE_INPAINT_INSERTION",
...baseSteps != null ? { editConfig: { baseSteps } } : {},
...otherOptions
}
};
} else {
body = {
instances: [{ prompt }],
parameters: {
sampleCount: n,
...aspectRatio != null ? { aspectRatio } : {},
...seed != null ? { seed } : {},
...otherOptions
}
};
}
const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
const { value: response, responseHeaders } = await postJsonToApi2({
url: `${this.config.baseURL}/models/${this.modelId}:predict`,
headers: combineHeaders2(await resolve2(this.config.headers), headers),
body,
failedResponseHandler: googleVertexFailedResponseHandler,
successfulResponseHandler: createJsonResponseHandler2(
vertexImageResponseSchema
),
abortSignal,
fetch: this.config.fetch
});
return {
images: (_e = (_d = response.predictions) == null ? void 0 : _d.map(
({ bytesBase64Encoded }) => bytesBase64Encoded
)) != null ? _e : [],
warnings,
response: {
timestamp: currentDate,
modelId: this.modelId,
headers: responseHeaders
},
providerMetadata: {
vertex: {
images: (_g = (_f = response.predictions) == null ? void 0 : _f.map((prediction) => {
const {
// normalize revised prompt property
prompt: revisedPrompt
} = prediction;
return { ...revisedPrompt != null && { revisedPrompt } };
})) != null ? _g : []
}
}
};
}
};
var vertexImageResponseSchema = z4.object({
predictions: z4.array(
z4.object({
bytesBase64Encoded: z4.string(),
mimeType: z4.string(),
prompt: z4.string().nullish()
})
).nullish()
});
var vertexImageProviderOptionsSchema = z4.object({
negativePrompt: z4.string().nullish(),
personGeneration: z4.enum(["dont_allow", "allow_adult", "allow_all"]).nullish(),
safetySetting: z4.enum([
"block_low_and_above",
"block_medium_and_above",
"block_only_high",
"block_none"
]).nullish(),
addWatermark: z4.boolean().nullish(),
storageUri: z4.string().nullish(),
sampleImageSize: z4.enum(["1K", "2K"]).nullish(),
/**
* Configuration for image editing operations
*/
edit: z4.object({
/**
* An integer that represents the number of sampling steps.
* A higher value offers better image quality, a lower value offers better latency.
* Try 35 steps to start. If the quality doesn't meet your requirements,
* increase the value towards an upper limit of 75.
*/
baseSteps: z4.number().nullish(),
// Edit mode options
// https://cloud.google.com/vertex-ai/generative-ai/docs/image/edit-insert-objects
mode: z4.enum([
"EDIT_MODE_INPAINT_INSERTION",
"EDIT_MODE_INPAINT_REMOVAL",
"EDIT_MODE_OUTPAINT",
"EDIT_MODE_CONTROLLED_EDITING",
"EDIT_MODE_PRODUCT_IMAGE",
"EDIT_MODE_BGSWAP"
]).nullish(),
/**
* The mask mode to use.
* - `MASK_MODE_DEFAULT` - Default value for mask mode.
* - `MASK_MODE_USER_PROVIDED` - User provided mask. No segmentation needed.
* - `MASK_MODE_DETECTION_BOX` - Mask from detected bounding boxes.
* - `MASK_MODE_CLOTHING_AREA` - Masks from segmenting the clothing area with open-vocab segmentation.
* - `MASK_MODE_PARSED_PERSON` - Masks from segmenting the person body and clothing using the person-parsing model.
*/
maskMode: z4.enum([
"MASK_MODE_DEFAULT",
"MASK_MODE_USER_PROVIDED",
"MASK_MODE_DETECTION_BOX",
"MASK_MODE_CLOTHING_AREA",
"MASK_MODE_PARSED_PERSON"
]).nullish(),
/**
* Optional. A float value between 0 and 1, inclusive, that represents the
* percentage of the image width to grow the mask by. Using dilation helps
* compensate for imprecise masks. We recommend a value of 0.01.
*/
maskDilation: z4.number().nullish()
}).nullish()
});
function getBase64Data(file) {
if (file.type === "url") {
throw new Error(
"URL-based images are not supported for Google Vertex image editing. Please provide the image data directly."
);
}
if (typeof file.data === "string") {
return file.data;
}
return convertUint8ArrayToBase64(file.data);
}
// src/google-vertex-tools.ts
import { googleTools } from "@ai-sdk/google/internal";
var googleVertexTools = {
googleSearch: googleTools.googleSearch,
enterpriseWebSearch: googleTools.enterpriseWebSearch,
googleMaps: googleTools.googleMaps,
urlContext: googleTools.urlContext,
fileSearch: googleTools.fileSearch,
codeExecution: googleTools.codeExecution,
vertexRagStore: googleTools.vertexRagStore
};
// src/google-vertex-provider.ts
var EXPRESS_MODE_BASE_URL = "https://aiplatform.googleapis.com/v1/publishers/google";
function createExpressModeFetch(apiKey, customFetch) {
return async (url, init) => {
const modifiedInit = {
...init,
headers: {
...(init == null ? void 0 : init.headers) ? normalizeHeaders(init.headers) : {},
"x-goog-api-key": apiKey
}
};
return (customFetch != null ? customFetch : fetch)(url.toString(), modifiedInit);
};
}
function createVertex(options = {}) {
const apiKey = loadOptionalSetting({
settingValue: options.apiKey,
environmentVariableName: "GOOGLE_VERTEX_API_KEY"
});
const loadVertexProject = () => loadSetting({
settingValue: options.project,
settingName: "project",
environmentVariableName: "GOOGLE_VERTEX_PROJECT",
description: "Google Vertex project"
});
const loadVertexLocation = () => loadSetting({
settingValue: options.location,
settingName: "location",
environmentVariableName: "GOOGLE_VERTEX_LOCATION",
description: "Google Vertex location"
});
const loadBaseURL = () => {
var _a, _b;
if (apiKey) {
return (_a = withoutTrailingSlash(options.baseURL)) != null ? _a : EXPRESS_MODE_BASE_URL;
}
const region = loadVertexLocation();
const project = loadVertexProject();
const baseHost = `${region === "global" ? "" : region + "-"}aiplatform.googleapis.com`;
return (_b = withoutTrailingSlash(options.baseURL)) != null ? _b : `https://${baseHost}/v1beta1/projects/${project}/locations/${region}/publishers/google`;
};
const createConfig = (name) => {
const getHeaders = async () => {
var _a;
const originalHeaders = await resolve3((_a = options.headers) != null ? _a : {});
return withUserAgentSuffix(
originalHeaders,
`ai-sdk/google-vertex/${VERSION}`
);
};
return {
provider: `google.vertex.${name}`,
headers: getHeaders,
fetch: apiKey ? createExpressModeFetch(apiKey, options.fetch) : options.fetch,
baseURL: loadBaseURL()
};
};
const createChatModel = (modelId) => {
var _a;
return new GoogleGenerativeAILanguageModel(modelId, {
...createConfig("chat"),
generateId: (_a = options.generateId) != null ? _a : generateId,
supportedUrls: () => ({
"*": [
// HTTP URLs:
/^https?:\/\/.*$/,
// Google Cloud Storage URLs:
/^gs:\/\/.*$/
]
})
});
};
const createEmbeddingModel = (modelId) => new GoogleVertexEmbeddingModel(modelId, createConfig("embedding"));
const createImageModel = (modelId) => new GoogleVertexImageModel(modelId, createConfig("image"));
const provider = function(modelId) {
if (new.target) {
throw new Error(
"The Google Vertex AI model function cannot be called with the new keyword."
);
}
return createChatModel(modelId);
};
provider.specificationVersion = "v3";
provider.languageModel = createChatModel;
provider.embeddingModel = createEmbeddingModel;
provider.textEmbeddingModel = createEmbeddingModel;
provider.image = createImageModel;
provider.imageModel = createImageModel;
provider.tools = googleVertexTools;
return provider;
}
// src/google-vertex-provider-node.ts
function createVertex2(options = {}) {
const apiKey = loadOptionalSetting2({
settingValue: options.apiKey,
environmentVariableName: "GOOGLE_VERTEX_API_KEY"
});
if (apiKey) {
return createVertex(options);
}
return createVertex({
...options,
headers: async () => ({
Authorization: `Bearer ${await generateAuthToken(
options.googleAuthOptions
)}`,
...await resolve4(options.headers)
})
});
}
var vertex = createVertex2();
export {
VERSION,
createVertex2 as createVertex,
vertex
};
//# sourceMappingURL=index.mjs.map