voyage-ai-provider
Version:
Voyage AI Provider for running Voyage AI models with Vercel AI SDK
484 lines (470 loc) • 17.3 kB
JavaScript
;
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