@ai-sdk/google-vertex
Version:
157 lines (138 loc) • 5.15 kB
text/typescript
import { getGoogleVertexRequestConfig } from '../google-vertex-model-catalog-config';
import { InvalidArgumentError } from '@ai-sdk/provider';
import {
createOpenAICompatible,
type OpenAICompatibleProvider,
} from '@ai-sdk/openai-compatible';
import {
isValidHostnamePart,
loadOptionalSetting,
loadSetting,
withoutTrailingSlash,
type FetchFunction,
type Resolvable,
} from '@ai-sdk/provider-utils';
import type { GoogleVertexMaasModelId } from './google-vertex-maas-options';
function transformGoogleVertexMaasRequestBody(args: Record<string, any>) {
const maxOutputTokens = getGoogleVertexRequestConfig(args.model).language
?.maxOutputTokens;
return maxOutputTokens != null && args.max_tokens === undefined
? { ...args, max_tokens: maxOutputTokens }
: args;
}
export interface GoogleVertexMaasProvider extends OpenAICompatibleProvider<
GoogleVertexMaasModelId,
string,
string,
string
> {}
export interface GoogleVertexMaasProviderSettings {
/**
* Google Cloud project ID. Defaults to the value of the `GOOGLE_VERTEX_PROJECT` environment variable.
*/
project?: string;
/**
* Google Cloud location/region. Defaults to the value of the `GOOGLE_VERTEX_LOCATION` environment variable.
* Use 'global' for the global endpoint.
*/
location?: string;
/**
* Base URL for the API calls. If not provided, will be constructed from project and location.
*/
baseURL?: string;
/**
* Headers to use for requests. Can be:
* - A headers object
* - A Promise that resolves to a headers object
* - A function that returns a headers object
* - A function that returns a Promise of a headers object
*/
headers?: Resolvable<Record<string, string | undefined>>;
/**
* Custom fetch implementation. You can use it as a middleware to intercept requests,
* or to provide a custom fetch implementation for e.g. testing.
*/
fetch?: FetchFunction;
}
/**
* 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.
*/
export function loadGoogleVertexMaasBaseURL(
options: Pick<
GoogleVertexMaasProviderSettings,
'baseURL' | 'project' | 'location'
>,
): string {
// Lazy-load settings to support loading from environment variables at runtime
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: string) => {
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
*/
export function createGoogleVertexMaas(
options: GoogleVertexMaasProviderSettings = {},
): GoogleVertexMaasProvider {
let cachedProvider: GoogleVertexMaasProvider | undefined;
const getProvider = () =>
(cachedProvider ??= createOpenAICompatible({
name: 'vertex.maas',
baseURL: loadGoogleVertexMaasBaseURL(options),
fetch: options.fetch,
transformRequestBody: transformGoogleVertexMaasRequestBody,
}));
const provider = (modelId: GoogleVertexMaasModelId) => getProvider()(modelId);
provider.specificationVersion = 'v4' as const;
provider.languageModel = (modelId: GoogleVertexMaasModelId) =>
getProvider().languageModel(modelId);
provider.chatModel = (modelId: GoogleVertexMaasModelId) =>
getProvider().chatModel(modelId);
provider.completionModel = (modelId: string) =>
getProvider().completionModel(modelId);
provider.embeddingModel = (modelId: string) =>
getProvider().embeddingModel(modelId);
provider.textEmbeddingModel = (modelId: string) =>
getProvider().textEmbeddingModel(modelId);
provider.imageModel = (modelId: string) => getProvider().imageModel(modelId);
return provider as GoogleVertexMaasProvider;
}