Skip to content
Snippets Groups Projects
Unverified Commit d0a3f1e3 authored by Timothy Carambat's avatar Timothy Carambat Committed by GitHub
Browse files

Fix present diminsions on vectorDBs to be inferred for providers who require it (#605)

parent f5bb064d
No related branches found
No related tags found
No related merge requests found
...@@ -13,7 +13,6 @@ class AzureOpenAiEmbedder { ...@@ -13,7 +13,6 @@ class AzureOpenAiEmbedder {
new AzureKeyCredential(process.env.AZURE_OPENAI_KEY) new AzureKeyCredential(process.env.AZURE_OPENAI_KEY)
); );
this.openai = openai; this.openai = openai;
this.dimensions = 1536;
// Limit of how many strings we can process in a single pass to stay with resource or network limits // Limit of how many strings we can process in a single pass to stay with resource or network limits
// https://learn.microsoft.com/en-us/azure/ai-services/openai/faq#i-am-trying-to-use-embeddings-and-received-the-error--invalidrequesterror--too-many-inputs--the-max-number-of-inputs-is-1---how-do-i-fix-this-:~:text=consisting%20of%20up%20to%2016%20inputs%20per%20API%20request // https://learn.microsoft.com/en-us/azure/ai-services/openai/faq#i-am-trying-to-use-embeddings-and-received-the-error--invalidrequesterror--too-many-inputs--the-max-number-of-inputs-is-1---how-do-i-fix-this-:~:text=consisting%20of%20up%20to%2016%20inputs%20per%20API%20request
......
...@@ -16,10 +16,6 @@ class LocalAiEmbedder { ...@@ -16,10 +16,6 @@ class LocalAiEmbedder {
: {}), : {}),
}); });
this.openai = new OpenAIApi(config); this.openai = new OpenAIApi(config);
// We don't know this for user's set model so for vectorDB integrations that requires dimensionality
// in schema, we will throw an error.
// Applies to QDrant and Milvus.
this.dimensions = null;
// Limit of how many strings we can process in a single pass to stay with resource or network limits // Limit of how many strings we can process in a single pass to stay with resource or network limits
this.maxConcurrentChunks = 50; this.maxConcurrentChunks = 50;
......
...@@ -13,7 +13,6 @@ class NativeEmbedder { ...@@ -13,7 +13,6 @@ class NativeEmbedder {
: path.resolve(__dirname, `../../../storage/models`) : path.resolve(__dirname, `../../../storage/models`)
); );
this.modelPath = path.resolve(this.cacheDir, "Xenova", "all-MiniLM-L6-v2"); this.modelPath = path.resolve(this.cacheDir, "Xenova", "all-MiniLM-L6-v2");
this.dimensions = 384;
// Limit of how many strings we can process in a single pass to stay with resource or network limits // Limit of how many strings we can process in a single pass to stay with resource or network limits
this.maxConcurrentChunks = 25; this.maxConcurrentChunks = 25;
......
...@@ -9,7 +9,6 @@ class OpenAiEmbedder { ...@@ -9,7 +9,6 @@ class OpenAiEmbedder {
}); });
const openai = new OpenAIApi(config); const openai = new OpenAIApi(config);
this.openai = openai; this.openai = openai;
this.dimensions = 1536;
// Limit of how many strings we can process in a single pass to stay with resource or network limits // Limit of how many strings we can process in a single pass to stay with resource or network limits
this.maxConcurrentChunks = 500; this.maxConcurrentChunks = 500;
......
...@@ -81,13 +81,15 @@ const Milvus = { ...@@ -81,13 +81,15 @@ const Milvus = {
await client.dropCollection({ collection_name: namespace }); await client.dropCollection({ collection_name: namespace });
return true; return true;
}, },
getOrCreateCollection: async function (client, namespace) { // Milvus requires a dimension aspect for collection creation
// we pass this in from the first chunk to infer the dimensions like other
// providers do.
getOrCreateCollection: async function (client, namespace, dimensions = null) {
const isExists = await this.namespaceExists(client, namespace); const isExists = await this.namespaceExists(client, namespace);
if (!isExists) { if (!isExists) {
const embedder = getEmbeddingEngineSelection(); if (!dimensions)
if (!embedder.dimensions)
throw new Error( throw new Error(
`Your embedder selection has unknown dimensions output. It should be defined when using ${this.name}. Open an issue on Github for support.` `Milvus:getOrCreateCollection Unable to infer vector dimension from input. Open an issue on Github for support.`
); );
await client.createCollection({ await client.createCollection({
...@@ -104,7 +106,7 @@ const Milvus = { ...@@ -104,7 +106,7 @@ const Milvus = {
name: "vector", name: "vector",
description: "vector", description: "vector",
data_type: DataType.FloatVector, data_type: DataType.FloatVector,
dim: embedder.dimensions, dim: dimensions,
}, },
{ {
name: "metadata", name: "metadata",
...@@ -131,6 +133,7 @@ const Milvus = { ...@@ -131,6 +133,7 @@ const Milvus = {
) { ) {
const { DocumentVectors } = require("../../../models/vectors"); const { DocumentVectors } = require("../../../models/vectors");
try { try {
let vectorDimension = null;
const { pageContent, docId, ...metadata } = documentData; const { pageContent, docId, ...metadata } = documentData;
if (!pageContent || pageContent.length == 0) return false; if (!pageContent || pageContent.length == 0) return false;
...@@ -138,11 +141,11 @@ const Milvus = { ...@@ -138,11 +141,11 @@ const Milvus = {
const cacheResult = await cachedVectorInformation(fullFilePath); const cacheResult = await cachedVectorInformation(fullFilePath);
if (cacheResult.exists) { if (cacheResult.exists) {
const { client } = await this.connect(); const { client } = await this.connect();
await this.getOrCreateCollection(client, namespace);
const { chunks } = cacheResult; const { chunks } = cacheResult;
const documentVectors = []; const documentVectors = [];
vectorDimension = chunks[0][0].values.length || null;
await this.getOrCreateCollection(client, namespace, vectorDimension);
for (const chunk of chunks) { for (const chunk of chunks) {
// Before sending to Pinecone and saving the records to our db // Before sending to Pinecone and saving the records to our db
// we need to assign the id of each chunk that is stored in the cached file. // we need to assign the id of each chunk that is stored in the cached file.
...@@ -182,6 +185,7 @@ const Milvus = { ...@@ -182,6 +185,7 @@ const Milvus = {
if (!!vectorValues && vectorValues.length > 0) { if (!!vectorValues && vectorValues.length > 0) {
for (const [i, vector] of vectorValues.entries()) { for (const [i, vector] of vectorValues.entries()) {
if (!vectorDimension) vectorDimension = vector.length;
const vectorRecord = { const vectorRecord = {
id: uuidv4(), id: uuidv4(),
values: vector, values: vector,
...@@ -202,7 +206,7 @@ const Milvus = { ...@@ -202,7 +206,7 @@ const Milvus = {
if (vectors.length > 0) { if (vectors.length > 0) {
const chunks = []; const chunks = [];
const { client } = await this.connect(); const { client } = await this.connect();
await this.getOrCreateCollection(client, namespace); await this.getOrCreateCollection(client, namespace, vectorDimension);
console.log("Inserting vectorized chunks into Milvus."); console.log("Inserting vectorized chunks into Milvus.");
for (const chunk of toChunks(vectors, 100)) { for (const chunk of toChunks(vectors, 100)) {
......
...@@ -108,19 +108,20 @@ const QDrant = { ...@@ -108,19 +108,20 @@ const QDrant = {
await client.deleteCollection(namespace); await client.deleteCollection(namespace);
return true; return true;
}, },
getOrCreateCollection: async function (client, namespace) { // QDrant requires a dimension aspect for collection creation
// we pass this in from the first chunk to infer the dimensions like other
// providers do.
getOrCreateCollection: async function (client, namespace, dimensions = null) {
if (await this.namespaceExists(client, namespace)) { if (await this.namespaceExists(client, namespace)) {
return await client.getCollection(namespace); return await client.getCollection(namespace);
} }
if (!dimensions)
const embedder = getEmbeddingEngineSelection();
if (!embedder.dimensions)
throw new Error( throw new Error(
`Your embedder selection has unknown dimensions output. It should be defined when using ${this.name}. Open an issue on Github for support.` `Qdrant:getOrCreateCollection Unable to infer vector dimension from input. Open an issue on Github for support.`
); );
await client.createCollection(namespace, { await client.createCollection(namespace, {
vectors: { vectors: {
size: embedder.dimensions, size: dimensions,
distance: "Cosine", distance: "Cosine",
}, },
}); });
...@@ -133,6 +134,7 @@ const QDrant = { ...@@ -133,6 +134,7 @@ const QDrant = {
) { ) {
const { DocumentVectors } = require("../../../models/vectors"); const { DocumentVectors } = require("../../../models/vectors");
try { try {
let vectorDimension = null;
const { pageContent, docId, ...metadata } = documentData; const { pageContent, docId, ...metadata } = documentData;
if (!pageContent || pageContent.length == 0) return false; if (!pageContent || pageContent.length == 0) return false;
...@@ -140,15 +142,20 @@ const QDrant = { ...@@ -140,15 +142,20 @@ const QDrant = {
const cacheResult = await cachedVectorInformation(fullFilePath); const cacheResult = await cachedVectorInformation(fullFilePath);
if (cacheResult.exists) { if (cacheResult.exists) {
const { client } = await this.connect(); const { client } = await this.connect();
const collection = await this.getOrCreateCollection(client, namespace); const { chunks } = cacheResult;
const documentVectors = [];
vectorDimension = chunks[0][0].vector.length || null;
const collection = await this.getOrCreateCollection(
client,
namespace,
vectorDimension
);
if (!collection) if (!collection)
throw new Error("Failed to create new QDrant collection!", { throw new Error("Failed to create new QDrant collection!", {
namespace, namespace,
}); });
const { chunks } = cacheResult;
const documentVectors = [];
for (const chunk of chunks) { for (const chunk of chunks) {
const submission = { const submission = {
ids: [], ids: [],
...@@ -210,6 +217,7 @@ const QDrant = { ...@@ -210,6 +217,7 @@ const QDrant = {
if (!!vectorValues && vectorValues.length > 0) { if (!!vectorValues && vectorValues.length > 0) {
for (const [i, vector] of vectorValues.entries()) { for (const [i, vector] of vectorValues.entries()) {
if (!vectorDimension) vectorDimension = vector.length;
const vectorRecord = { const vectorRecord = {
id: uuidv4(), id: uuidv4(),
vector: vector, vector: vector,
...@@ -233,7 +241,11 @@ const QDrant = { ...@@ -233,7 +241,11 @@ const QDrant = {
} }
const { client } = await this.connect(); const { client } = await this.connect();
const collection = await this.getOrCreateCollection(client, namespace); const collection = await this.getOrCreateCollection(
client,
namespace,
vectorDimension
);
if (!collection) if (!collection)
throw new Error("Failed to create new QDrant collection!", { throw new Error("Failed to create new QDrant collection!", {
namespace, namespace,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment