ai
Version:
AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.
310 lines (270 loc) • 10 kB
text/typescript
import { gateway } from '@ai-sdk/gateway';
import {
NoSuchModelError,
type Experimental_DecisionModelV4 as DecisionModelV4,
type EmbeddingModelV4,
type Experimental_ExtractionModelV4 as ExtractionModelV4,
type Experimental_SpeechTranslationModelV4,
type Experimental_VideoModelV4,
type ImageModelV4,
type LanguageModelV4,
type ProviderV4,
type RerankingModelV4,
type SpeechModelV4,
type TranscriptionModelV4,
} from '@ai-sdk/provider';
import type { DecisionModel } from '../decide/decision-result';
import type { DecisionProvider } from '../decide/decision-provider';
import { UnsupportedModelVersionError } from '../error';
import type { ExtractionModel } from '../extract/extraction-result';
import type { EmbeddingModel } from '../types/embedding-model';
import type { LanguageModel } from '../types/language-model';
import type { SpeechModel } from '../types/speech-model';
import type { SpeechTranslationModel } from '../types/speech-translation-model';
import type { TranscriptionModel } from '../types/transcription-model';
import { asEmbeddingModelV4 } from './as-embedding-model-v4';
import { asImageModelV4 } from './as-image-model-v4';
import { asLanguageModelV4 } from './as-language-model-v4';
import { asRerankingModelV4 } from './as-reranking-model-v4';
import { asSpeechModelV4 } from './as-speech-model-v4';
import { asTranscriptionModelV4 } from './as-transcription-model-v4';
import { asVideoModelV4 } from './as-video-model-v4';
import { asProviderV4 } from './as-provider-v4';
import type { ImageModel } from '../types/image-model';
import type { RerankingModel } from '../types/reranking-model';
import type { VideoModel } from '../types/video-model';
export function resolveLanguageModel(model: LanguageModel): LanguageModelV4 {
if (typeof model === 'string') {
return getGlobalProvider().languageModel(model);
}
if (!['v4', 'v3', 'v2'].includes(model.specificationVersion)) {
const unsupportedModel: any = model;
throw new UnsupportedModelVersionError({
version: unsupportedModel.specificationVersion,
provider: unsupportedModel.provider,
modelId: unsupportedModel.modelId,
});
}
return asLanguageModelV4(model);
}
export function resolveEmbeddingModel(model: EmbeddingModel): EmbeddingModelV4 {
if (typeof model === 'string') {
return getGlobalProvider().embeddingModel(model);
}
if (!['v4', 'v3', 'v2'].includes(model.specificationVersion)) {
const unsupportedModel: any = model;
throw new UnsupportedModelVersionError({
version: unsupportedModel.specificationVersion,
provider: unsupportedModel.provider,
modelId: unsupportedModel.modelId,
});
}
return asEmbeddingModelV4(model);
}
export function resolveTranscriptionModel(
model: TranscriptionModel,
): TranscriptionModelV4 | undefined {
if (typeof model === 'string') {
return getGlobalProvider().transcriptionModel?.(model);
}
if (!['v4', 'v3', 'v2'].includes(model.specificationVersion)) {
const unsupportedModel: any = model;
throw new UnsupportedModelVersionError({
version: unsupportedModel.specificationVersion,
provider: unsupportedModel.provider,
modelId: unsupportedModel.modelId,
});
}
return asTranscriptionModelV4(model);
}
export function resolveSpeechTranslationModel(
model: SpeechTranslationModel,
): Experimental_SpeechTranslationModelV4 {
if (typeof model === 'string') {
// Use raw global provider because speechTranslationModel is experimental
// and not part of the ProviderV4 interface
const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? gateway;
// TODO AI SDK v7
// @ts-expect-error - speechTranslationModel support is experimental
const speechTranslationModel = provider.speechTranslationModel;
if (!speechTranslationModel) {
throw new Error(
'The default provider does not support speech translation models. ' +
'Please pass a provider model instance that implements the experimental speech translation model specification.',
);
}
return speechTranslationModel(model);
}
if (model.specificationVersion !== 'v4') {
const unsupportedModel: any = model;
throw new UnsupportedModelVersionError({
version: unsupportedModel.specificationVersion,
provider: unsupportedModel.provider,
modelId: unsupportedModel.modelId,
});
}
return model;
}
export function resolveSpeechModel(
model: SpeechModel,
): SpeechModelV4 | undefined {
if (typeof model === 'string') {
return getGlobalProvider().speechModel?.(model);
}
if (!['v4', 'v3', 'v2'].includes(model.specificationVersion)) {
const unsupportedModel: any = model;
throw new UnsupportedModelVersionError({
version: unsupportedModel.specificationVersion,
provider: unsupportedModel.provider,
modelId: unsupportedModel.modelId,
});
}
return asSpeechModelV4(model);
}
export function resolveImageModel(model: ImageModel): ImageModelV4 {
if (typeof model === 'string') {
return getGlobalProvider().imageModel(model);
}
if (!['v4', 'v3', 'v2'].includes(model.specificationVersion)) {
const unsupportedModel: any = model;
throw new UnsupportedModelVersionError({
version: unsupportedModel.specificationVersion,
provider: unsupportedModel.provider,
modelId: unsupportedModel.modelId,
});
}
return asImageModelV4(model);
}
export function resolveVideoModel(
model: VideoModel,
): Experimental_VideoModelV4 {
if (typeof model === 'string') {
// Use raw global provider because videoModel is experimental
// and not part of the ProviderV4 interface
const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? gateway;
// TODO AI SDK v7
// @ts-expect-error - videoModel support is experimental
const videoModel = provider.videoModel;
if (!videoModel) {
throw new Error(
'The default provider does not support video models. ' +
'Please use a Experimental_VideoModelV4 object from a provider (e.g., vertex.video("model-id")).',
);
}
return videoModel(model);
}
if (!['v4', 'v3'].includes(model.specificationVersion)) {
const unsupportedModel: any = model;
throw new UnsupportedModelVersionError({
version: unsupportedModel.specificationVersion,
provider: unsupportedModel.provider,
modelId: unsupportedModel.modelId,
});
}
return asVideoModelV4(model);
}
export function resolveRerankingModel(model: RerankingModel): RerankingModelV4 {
if (typeof model === 'string') {
const provider = getGlobalProvider();
const rerankingModel = provider.rerankingModel;
if (!rerankingModel) {
throw new Error(
'The default provider does not support reranking models. ' +
'Please use a RerankingModel object from a provider (e.g., gateway.rerankingModel("model-id")).',
);
}
return rerankingModel(model);
}
if (
model.specificationVersion !== 'v4' &&
model.specificationVersion !== 'v3'
) {
const unsupportedModel: any = model;
throw new UnsupportedModelVersionError({
version: unsupportedModel.specificationVersion,
provider: unsupportedModel.provider,
modelId: unsupportedModel.modelId,
});
}
return asRerankingModelV4(model);
}
export function resolveDecisionModel(model: DecisionModel): DecisionModelV4 {
if (typeof model === 'string') {
// Use the original provider so experimental methods and their receiver survive.
const provider = (globalThis.AI_SDK_DEFAULT_PROVIDER ??
gateway) as DecisionProvider;
const factory:
| ((modelId: string) => Exclude<DecisionModel, string>)
| undefined = provider.decisionModel ?? provider.evaluationModel;
if (typeof factory !== 'function') {
throw new NoSuchModelError({
modelId: model,
modelType: 'decisionModel',
message:
'The default provider does not support decision models. ' +
'Pass a decision model instance or configure AI_SDK_DEFAULT_PROVIDER with a decisionModel method.',
});
}
const resolvedModel = factory.call(provider, model);
if (resolvedModel == null) {
throw new NoSuchModelError({
modelId: model,
modelType: 'decisionModel',
});
}
model = resolvedModel;
}
if (model.specificationVersion !== 'v4') {
throw new UnsupportedModelVersionError({
version: model.specificationVersion,
provider: model.provider,
modelId: model.modelId,
});
}
if ('doDecide' in model) {
return model;
}
const legacyModel = model;
return {
specificationVersion: legacyModel.specificationVersion,
provider: legacyModel.provider,
modelId: legacyModel.modelId,
supportedQuestionTypes: legacyModel.supportedQuestionTypes,
doDecide: options => legacyModel.doEvaluate(options),
};
}
export function resolveExtractionModel(
model: ExtractionModel,
): ExtractionModelV4 {
const version: string = model.specificationVersion;
if (version !== 'v4') {
throw new UnsupportedModelVersionError({
version,
provider: model.provider,
modelId: model.modelId,
});
}
return model;
}
function getGlobalProvider(): ProviderV4 {
const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? gateway;
return asProviderV4(provider);
}
/** Internal adapter for deprecated provider factories. */
export function asEvaluationModel(model: DecisionModelV4): DecisionModelV4 & {
doEvaluate: DecisionModelV4['doDecide'];
} {
if ('doEvaluate' in model && typeof model.doEvaluate === 'function') {
return model as DecisionModelV4 & {
doEvaluate: DecisionModelV4['doDecide'];
};
}
return {
specificationVersion: model.specificationVersion,
provider: model.provider,
modelId: model.modelId,
supportedQuestionTypes: model.supportedQuestionTypes,
doDecide: options => model.doDecide(options),
doEvaluate: options => model.doDecide(options),
};
}