UNPKG

@ai-sdk/google-vertex

Version:
224 lines (223 loc) • 8.73 kB
import { fetchWithValidatedEndpoint, getRuntimeEnvironmentUserAgent, isBrowserRuntime, isSameOrigin, isValidHostnamePart, loadOptionalSetting, loadSetting, resolve, withUserAgentSuffix, withoutTrailingSlash } from "@ai-sdk/provider-utils"; import { InvalidArgumentError } from "@ai-sdk/provider"; import { createOpenAICompatible } from "@ai-sdk/openai-compatible"; //#region src/version.ts const VERSION = "5.0.141"; //#endregion //#region src/edge/google-vertex-auth-edge.ts const loadCredentials = async () => { try { return { clientEmail: loadSetting({ settingValue: void 0, settingName: "clientEmail", environmentVariableName: "GOOGLE_CLIENT_EMAIL", description: "Google client email" }), privateKey: loadSetting({ settingValue: void 0, settingName: "privateKey", environmentVariableName: "GOOGLE_PRIVATE_KEY", description: "Google private key" }), privateKeyId: loadOptionalSetting({ settingValue: void 0, environmentVariableName: "GOOGLE_PRIVATE_KEY_ID" }) }; } catch (error) { throw new Error(`Failed to load Google credentials: ${error.message}`); } }; const base64url = (str) => { return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, ""); }; const importPrivateKey = async (pemKey) => { const pemContents = pemKey.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replace(/\s/g, ""); const binaryString = atob(pemContents); const binaryData = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) binaryData[i] = binaryString.charCodeAt(i); return await crypto.subtle.importKey("pkcs8", binaryData, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, true, ["sign"]); }; const buildJwt = async (credentials) => { const now = Math.floor(Date.now() / 1e3); const header = { alg: "RS256", typ: "JWT" }; if (credentials.privateKeyId) header.kid = credentials.privateKeyId; const payload = { iss: credentials.clientEmail, scope: "https://www.googleapis.com/auth/cloud-platform", aud: "https://oauth2.googleapis.com/token", exp: now + 3600, iat: now }; const privateKey = await importPrivateKey(credentials.privateKey); const signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`; const data = new TextEncoder().encode(signingInput); const signature = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", privateKey, data); const signatureBase64 = base64url(String.fromCharCode(...new Uint8Array(signature))); return `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}.${signatureBase64}`; }; /** * Generate an authentication token for Google Vertex AI in a manner compatible * with the Edge runtime. */ async function generateAuthToken(credentials) { const creds = credentials || await loadCredentials(); const jwt = await buildJwt(creds); const response = await fetch("https://oauth2.googleapis.com/token", { method: "POST", headers: withUserAgentSuffix({ "Content-Type": "application/x-www-form-urlencoded" }, `ai-sdk-google-vertex/${VERSION}`, getRuntimeEnvironmentUserAgent()), body: new URLSearchParams({ grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer", assertion: jwt }) }); if (!response.ok) throw new Error(`Token request failed: ${response.statusText}`); return (await response.json()).access_token; } //#endregion //#region src/google-vertex-model-catalog-config.ts function requestConfig(modelId) { const embedContent = modelId === "gemini-embedding-2" || modelId === "gemini-embedding-2-preview"; return { language: { endpoint: modelId.startsWith("endpoints/"), maxOutputTokens: modelId === "meta/llama-4-maverick-17b-128e-instruct-maas" || modelId === "meta/llama-4-scout-17b-16e-instruct-maas" ? 8192 : void 0 }, image: { gemini: modelId.startsWith("gemini-") }, embedding: { endpoint: embedContent ? "embedContent" : "predict", maxEmbeddingsPerCall: embedContent ? 1 : 250 }, speech: { api: modelId.startsWith("chirp") ? "cloud-tts" : "gemini" }, transcription: { api: modelId.startsWith("gemini") ? "gemini" : "cloud-speech", live: modelId.includes("-live") } }; } function getGoogleVertexRequestConfig(modelId) { return requestConfig(modelId); } //#endregion //#region src/maas/google-vertex-maas-provider.ts function transformGoogleVertexMaasRequestBody(args) { const maxOutputTokens = getGoogleVertexRequestConfig(args.model).language?.maxOutputTokens; return maxOutputTokens != null && args.max_tokens === void 0 ? { ...args, max_tokens: maxOutputTokens } : args; } /** * Loads the base URL of the MaaS API from the settings or from the project and * location. Settings are loaded on each call so environment variables are read * at runtime. */ function loadGoogleVertexMaasBaseURL(options) { const loadLocation = () => { const location = loadOptionalSetting({ settingValue: options.location, environmentVariableName: "GOOGLE_VERTEX_LOCATION" }) ?? "global"; if (!isValidHostnamePart(location)) throw new InvalidArgumentError({ argument: "location", message: "Invalid Google Vertex location. Expected a single DNS label (letters, digits, and hyphens). Use `baseURL` for custom endpoints." }); return location; }; const loadProject = () => loadSetting({ settingValue: options.project, settingName: "project", environmentVariableName: "GOOGLE_VERTEX_PROJECT", description: "Google Vertex project" }); const getHost = (location) => { if (location === "global") return "aiplatform.googleapis.com"; else if (location === "eu" || location === "us") return `aiplatform.${location}.rep.googleapis.com`; else return `${location}-aiplatform.googleapis.com`; }; const constructBaseURL = () => { const projectId = loadProject(); const location = loadLocation(); return `https://${getHost(location)}/v1/projects/${projectId}/locations/${location}/endpoints/openapi`; }; return withoutTrailingSlash(options.baseURL ?? "") || constructBaseURL(); } /** * Create a Google Vertex AI MaaS (Model as a Service) provider instance. * Uses the OpenAI-compatible Chat Completions API for partner and open models. * * @see https://cloud.google.com/vertex-ai/generative-ai/docs/maas/use-open-models */ function createGoogleVertexMaas$1(options = {}) { let cachedProvider; const getProvider = () => cachedProvider ??= createOpenAICompatible({ name: "vertex.maas", baseURL: loadGoogleVertexMaasBaseURL(options), fetch: options.fetch, transformRequestBody: transformGoogleVertexMaasRequestBody }); const provider = (modelId) => getProvider()(modelId); provider.specificationVersion = "v4"; provider.languageModel = (modelId) => getProvider().languageModel(modelId); provider.chatModel = (modelId) => getProvider().chatModel(modelId); provider.completionModel = (modelId) => getProvider().completionModel(modelId); provider.embeddingModel = (modelId) => getProvider().embeddingModel(modelId); provider.textEmbeddingModel = (modelId) => getProvider().textEmbeddingModel(modelId); provider.imageModel = (modelId) => getProvider().imageModel(modelId); return provider; } //#endregion //#region src/maas/edge/google-vertex-maas-provider-edge.ts /** * Create a Google Vertex AI MaaS (Model as a Service) provider instance for Edge runtimes. * Uses the OpenAI-compatible Chat Completions API for partner and open models. * Automatically handles Google Cloud authentication. * * @see https://cloud.google.com/vertex-ai/generative-ai/docs/maas/use-open-models */ function createGoogleVertexMaas(options = {}) { const customFetch = async (url, init) => { const href = typeof url === "string" ? url : url instanceof URL ? url.href : url.url; if (!isSameOrigin(href, loadGoogleVertexMaasBaseURL(options))) { if (isBrowserRuntime() && init?.redirect === "follow") return (options.fetch ?? fetch)(url, init); return fetchWithValidatedEndpoint({ url: href, init, fetch: options.fetch, redirect: "manual" }); } const token = await generateAuthToken(options.googleCredentials); const authHeaders = { ...await resolve(options.headers), Authorization: `Bearer ${token}` }; const fetchInit = { ...init, headers: { ...init?.headers, ...authHeaders } }; return (options.fetch ?? fetch)(url, fetchInit); }; return createGoogleVertexMaas$1({ ...options, fetch: customFetch, headers: void 0 }); } /** * Default Google Vertex AI MaaS provider instance for Edge runtimes. */ const googleVertexMaas = createGoogleVertexMaas(); //#endregion export { createGoogleVertexMaas, createGoogleVertexMaas as createVertexMaas, googleVertexMaas, googleVertexMaas as vertexMaas }; //# sourceMappingURL=index.js.map