UNPKG

voyage-ai-provider

Version:

Voyage AI Provider for running Voyage AI models with Vercel AI SDK

484 lines (470 loc) 17.3 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { createVoyage: () => createVoyage, voyage: () => voyage }); module.exports = __toCommonJS(index_exports); // src/voyage-provider.ts var import_provider_utils7 = require("@ai-sdk/provider-utils"); // src/voyage-embedding-model.ts var import_provider = require("@ai-sdk/provider"); var import_provider_utils2 = require("@ai-sdk/provider-utils"); var import_v43 = require("zod/v4"); // src/voyage-embedding-settings.ts var import_v4 = require("zod/v4"); var voyageEmbeddingOptions = import_v4.z.object({ /** * The input type for the embeddings. Defaults to "query". * For query, the prompt is "Represent the query for retrieving supporting documents: ". * For document, the prompt is "Represent the document for retrieval: ". */ inputType: import_v4.z.enum(["query", "document"]).optional(), // /** // * Format in which the embeddings are encoded. We support two options: // * If not specified (defaults to null): the embeddings are represented as lists of floating-point numbers; // * base64: the embeddings are compressed to base64 encodings. // */ // encodingFormat?: 'base64'; /** * The number of dimensions for the resulting output embeddings. * * If not specified (defaults to null), the resulting output embeddings dimension is the default for the model. * `voyage-code-3` supports the following `outputDimension` values: 2048, 1024 (default), 512, and 256. * `voyage-3-large` supports the following `outputDimension` values: 2048, 1024 (default), 512, and 256. * * please refer to the model documentation for the supported values. * https://docs.voyageai.com/docs/embeddings */ outputDimension: import_v4.z.number().optional(), /** * The data type for the resulting output embeddings. * * Defaults to 'float'. * * Other options: 'int8', 'uint8', 'binary', 'ubinary'. * - 'float' is supported by all models. * - 'float': Each returned embedding is a list of 32-bit (4-byte) single-precision floating-point numbers. * - 'int8', 'uint8', 'binary', and 'ubinary' are supported by 'voyage-code-3'. * - 'int8' and 'uint8': Each returned embedding is a list of 8-bit (1-byte) integers ranging from -128 to 127 and 0 to 255, respectively. * - 'binary' and 'ubinary': Each returned embedding is a list of 8-bit integers that represent bit-packed, quantized single-bit embedding values: * 'int8' for 'binary' and 'uint8' for 'ubinary'. * The length of the returned list of integers is 1/8 of outputDimension (which is the actual dimension of the embedding). * The 'binary' type uses the offset binary method. * * https://docs.voyageai.com/docs/faq#what-is-quantization-and-output-data-types */ outputDtype: import_v4.z.enum(["float", "int8", "uint8", "binary", "ubinary"]).optional(), /** * Whether to truncate the input texts to fit within the context length. */ truncation: import_v4.z.boolean().optional() }); // src/voyage-error.ts var import_provider_utils = require("@ai-sdk/provider-utils"); var import_v42 = require("zod/v4"); var voyageErrorDataSchema = import_v42.z.object({ error: import_v42.z.object({ code: import_v42.z.string().nullable(), message: import_v42.z.string(), param: import_v42.z.any().nullable(), type: import_v42.z.string() }) }); var voyageFailedResponseHandler = (0, import_provider_utils.createJsonErrorResponseHandler)({ errorSchema: voyageErrorDataSchema, errorToMessage: (data) => data.error.message }); // src/voyage-embedding-model.ts var VoyageEmbeddingModel = class { specificationVersion = "v3"; modelId; config; get provider() { return this.config.provider; } get maxEmbeddingsPerCall() { return 128; } get supportsParallelCalls() { return false; } constructor(modelId, config) { this.modelId = modelId; this.config = config; } async doEmbed({ abortSignal, values, headers, providerOptions }) { const embeddingOptions = await (0, import_provider_utils2.parseProviderOptions)({ provider: "voyage", providerOptions, schema: voyageEmbeddingOptions }); if (values.length > this.maxEmbeddingsPerCall) { throw new import_provider.TooManyEmbeddingValuesForCallError({ maxEmbeddingsPerCall: this.maxEmbeddingsPerCall, modelId: this.modelId, provider: this.provider, values }); } const { responseHeaders, value: response, rawValue } = await (0, import_provider_utils2.postJsonToApi)({ abortSignal, body: { input: values, model: this.modelId, input_type: embeddingOptions?.inputType, truncation: embeddingOptions?.truncation, output_dimension: embeddingOptions?.outputDimension, output_dtype: embeddingOptions?.outputDtype }, failedResponseHandler: voyageFailedResponseHandler, fetch: this.config.fetch, headers: (0, import_provider_utils2.combineHeaders)(this.config.headers(), headers), successfulResponseHandler: (0, import_provider_utils2.createJsonResponseHandler)( voyageTextEmbeddingResponseSchema ), url: `${this.config.baseURL}/embeddings` }); return { embeddings: response.data.map((item) => item.embedding), usage: response.usage ? { tokens: response.usage.total_tokens } : void 0, response: { headers: responseHeaders, body: rawValue }, warnings: [] }; } }; var voyageTextEmbeddingResponseSchema = import_v43.z.object({ data: import_v43.z.array(import_v43.z.object({ embedding: import_v43.z.array(import_v43.z.number()) })), usage: import_v43.z.object({ total_tokens: import_v43.z.number() }).nullish() }); // src/voyage-multimodal-embedding-model.ts var import_provider2 = require("@ai-sdk/provider"); var import_provider_utils3 = require("@ai-sdk/provider-utils"); // src/voyage-multimodal-embedding-settings.ts var import_v44 = require("zod/v4"); var voyageMultimodalContentPart = import_v44.z.union([ import_v44.z.object({ type: import_v44.z.literal("text"), text: import_v44.z.string() }), import_v44.z.object({ type: import_v44.z.literal("image_url"), image_url: import_v44.z.string() }), import_v44.z.object({ type: import_v44.z.literal("image_base64"), image_base64: import_v44.z.string() }) ]); var voyageMultimodalEmbeddingOptions = import_v44.z.object({ /** * Type of the input. * Defaults to "query". * * When input_type is specified as "query" or "document", Voyage automatically prepends a prompt * to your inputs before vectorize them, creating vectors more tailored for retrieval/search tasks. * * For retrieval/search purposes where a query is used to search through documents, we recommend * specifying whether your inputs are queries or documents. Since inputs can be multimodal, * "queries" and "documents" can be text, images, or an interleaving of both modalities. * * For transparency, the following prompts are prepended: * - For "query": "Represent the query for retrieving supporting documents: " * - For "document": "Represent the document for retrieval: " */ inputType: import_v44.z.enum(["query", "document"]).optional(), /** * The data type for the resulting output embeddings. * * Defaults to null. * * - If null, the embeddings are represented as a list of floating-point numbers. * - If base64, the embeddings are represented as a Base64-encoded NumPy array of single-precision floats. * * https://docs.voyageai.com/docs/faq#what-is-quantization-and-output-data-types */ outputEncoding: import_v44.z.enum(["base64"]).optional(), /** * Whether to truncate the input texts to fit within the context length. * * Defaults to true. */ truncation: import_v44.z.boolean().optional(), /** * Per-value multimodal content parts for embedding non-text content * (images). Each entry corresponds to the embedding value at the same * index and its parts are merged after the text value in the request. * Use `null` for entries that are text-only. * * The array length must match the number of values being embedded. * * https://docs.voyageai.com/reference/multimodal-embeddings-api */ content: import_v44.z.array(import_v44.z.array(voyageMultimodalContentPart).min(1).nullable()).optional() }); // src/voyage-multimodal-embedding-model.ts var import_v45 = require("zod/v4"); var MultimodalEmbeddingModel = class { specificationVersion = "v3"; modelId; config; get provider() { return this.config.provider; } get maxEmbeddingsPerCall() { return 128; } get supportsParallelCalls() { return false; } constructor(modelId, config) { this.modelId = modelId; this.config = config; } async doEmbed({ abortSignal, values, headers, providerOptions }) { const embeddingOptions = await (0, import_provider_utils3.parseProviderOptions)({ provider: "voyage", providerOptions, schema: voyageMultimodalEmbeddingOptions }); if (values.length > this.maxEmbeddingsPerCall) { throw new import_provider2.TooManyEmbeddingValuesForCallError({ maxEmbeddingsPerCall: this.maxEmbeddingsPerCall, modelId: this.modelId, provider: this.provider, values }); } const multimodalContent = embeddingOptions?.content; if (multimodalContent != null && multimodalContent.length !== values.length) { throw new Error( `The number of multimodal content entries (${multimodalContent.length}) must match the number of values (${values.length}).` ); } const inputs = values.map((value, index) => { const valueParts = multimodalContent?.[index]; const textPart = value ? [{ type: "text", text: value }] : []; return { content: valueParts != null ? [...textPart, ...valueParts] : [{ type: "text", text: value }] }; }); const { responseHeaders, value: response, rawValue } = await (0, import_provider_utils3.postJsonToApi)({ abortSignal, body: { inputs, model: this.modelId, input_type: embeddingOptions?.inputType, truncation: embeddingOptions?.truncation, output_encoding: embeddingOptions?.outputEncoding }, failedResponseHandler: voyageFailedResponseHandler, fetch: this.config.fetch, headers: (0, import_provider_utils3.combineHeaders)(this.config.headers(), headers), successfulResponseHandler: (0, import_provider_utils3.createJsonResponseHandler)( voyageMultimodalEmbeddingResponseSchema ), url: `${this.config.baseURL}/multimodalembeddings` }); return { embeddings: response.data.map((item) => item.embedding), usage: response.usage ? { tokens: response.usage.total_tokens } : void 0, response: { headers: responseHeaders, body: rawValue }, warnings: [] }; } }; var voyageMultimodalEmbeddingResponseSchema = import_v45.z.object({ data: import_v45.z.array( import_v45.z.object({ object: import_v45.z.literal("embedding"), embedding: import_v45.z.array(import_v45.z.number()), index: import_v45.z.number() }) ), usage: import_v45.z.object({ text_tokens: import_v45.z.number().nullish(), image_pixels: import_v45.z.number().nullish(), total_tokens: import_v45.z.number() }), model: import_v45.z.string() }); // src/reranking/voyage-reranking-model.ts var import_provider_utils6 = require("@ai-sdk/provider-utils"); // src/reranking/voyage-reranking-api.ts var import_provider_utils4 = require("@ai-sdk/provider-utils"); var import_v46 = require("zod/v4"); var voyageRerankingResponseSchema = (0, import_provider_utils4.lazySchema)( () => (0, import_provider_utils4.zodSchema)( import_v46.z.object({ object: import_v46.z.literal("list"), data: import_v46.z.array( import_v46.z.object({ relevance_score: import_v46.z.number(), index: import_v46.z.number() }) ), model: import_v46.z.string(), usage: import_v46.z.object({ total_tokens: import_v46.z.number() }) }) ) ); // src/reranking/voyage-reranking-options.ts var import_provider_utils5 = require("@ai-sdk/provider-utils"); var import_v47 = require("zod/v4"); var voyageRerankingOptionsSchema = (0, import_provider_utils5.lazySchema)( () => (0, import_provider_utils5.zodSchema)( import_v47.z.object({ returnDocuments: import_v47.z.boolean().optional(), truncation: import_v47.z.boolean().optional() }) ) ); // src/reranking/voyage-reranking-model.ts var VoyageRerankingModel = class { specificationVersion = "v3"; modelId; config; constructor(modelId, config) { this.modelId = modelId; this.config = config; } get provider() { return this.config.provider; } // current implementation is based on the API:https://docs.voyageai.com/reference/reranker-api async doRerank({ documents, headers, query, topN, abortSignal, providerOptions }) { const rerankingOptions = await (0, import_provider_utils6.parseProviderOptions)({ provider: "voyage", providerOptions, schema: voyageRerankingOptionsSchema }); const warnings = []; const { responseHeaders, value: response, rawValue } = await (0, import_provider_utils6.postJsonToApi)({ url: `${this.config.baseURL}/rerank`, headers: (0, import_provider_utils6.combineHeaders)(this.config.headers(), headers), body: { model: this.modelId, query, documents: documents.type === "text" ? documents.values : documents.values.map((value) => JSON.stringify(value)), top_k: topN, return_documents: rerankingOptions?.returnDocuments ?? false, truncation: rerankingOptions?.truncation ?? true }, failedResponseHandler: voyageFailedResponseHandler, successfulResponseHandler: (0, import_provider_utils6.createJsonResponseHandler)( voyageRerankingResponseSchema ), abortSignal, fetch: this.config.fetch }); return { ranking: response.data.map((result) => ({ index: result.index, relevanceScore: result.relevance_score })), warnings: warnings.length > 0 ? warnings : void 0, response: { headers: responseHeaders, body: rawValue } }; } }; // src/voyage-provider.ts function createVoyage(options = {}) { const baseURL = (0, import_provider_utils7.withoutTrailingSlash)(options.baseURL) ?? "https://api.voyageai.com/v1"; const getHeaders = () => ({ Authorization: `Bearer ${(0, import_provider_utils7.loadApiKey)({ apiKey: options.apiKey, environmentVariableName: "VOYAGE_API_KEY", description: "Voyage" })}`, ...options.headers }); const createEmbeddingModel = (modelId) => new VoyageEmbeddingModel(modelId, { provider: "voyage.embedding", baseURL, headers: getHeaders, fetch: options.fetch }); const createMultimodalEmbeddingModel = (modelId) => new MultimodalEmbeddingModel(modelId, { provider: "voyage.multimodal.embedding", baseURL, headers: getHeaders, fetch: options.fetch }); const createRerankingModel = (modelId) => new VoyageRerankingModel(modelId, { provider: "voyage.reranking", baseURL, headers: getHeaders, fetch: options.fetch }); const provider = function(modelId) { if (new.target) { throw new Error( "The Voyage model function cannot be called with the new keyword." ); } return createEmbeddingModel(modelId); }; provider.embeddingModel = createEmbeddingModel; provider.textEmbeddingModel = createEmbeddingModel; provider.multimodalEmbeddingModel = createMultimodalEmbeddingModel; provider.imageEmbeddingModel = createMultimodalEmbeddingModel; provider.chat = provider.languageModel = () => { throw new Error("languageModel method is not implemented."); }; provider.imageModel = () => { throw new Error("imageModel method is not implemented."); }; provider.reranking = createRerankingModel; provider.rerankingModel = createRerankingModel; return provider; } var voyage = createVoyage(); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { createVoyage, voyage }); //# sourceMappingURL=index.cjs.map