diff --git a/frontend/src/components/ChangeWarning/index.jsx b/frontend/src/components/ChangeWarning/index.jsx
index 42b211baf4..2e0950a080 100644
--- a/frontend/src/components/ChangeWarning/index.jsx
+++ b/frontend/src/components/ChangeWarning/index.jsx
@@ -1,4 +1,4 @@
-import { Warning } from "@phosphor-icons/react";
+import { Warning, X } from "@phosphor-icons/react";
export default function ChangeWarningModal({
warningText = "",
@@ -6,41 +6,55 @@ export default function ChangeWarningModal({
onConfirm,
}) {
return (
-
-
-
-
-
-
Warning
-
+
+
+
+
+
+ WARNING - This action is irreversible
+
-
-
- {warningText}
+
+
+
+
+
+ {warningText.split("\\n").map((line, index) => (
+
+ {line}
+
+
+ ))}
Are you sure you want to proceed?
-
-
-
-
-
+
+
+
+
);
diff --git a/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx b/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx
index 893948472d..77853e0a99 100644
--- a/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx
+++ b/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx
@@ -361,7 +361,7 @@ export default function GeneralEmbeddingPreference() {
)}
diff --git a/frontend/src/pages/GeneralSettings/VectorDatabase/index.jsx b/frontend/src/pages/GeneralSettings/VectorDatabase/index.jsx
index f7246de542..11e70d8fd7 100644
--- a/frontend/src/pages/GeneralSettings/VectorDatabase/index.jsx
+++ b/frontend/src/pages/GeneralSettings/VectorDatabase/index.jsx
@@ -308,7 +308,7 @@ export default function GeneralVectorDatabase() {
)}
diff --git a/server/models/vectors.js b/server/models/vectors.js
index f6b79964a0..3653303da2 100644
--- a/server/models/vectors.js
+++ b/server/models/vectors.js
@@ -25,6 +25,19 @@ const DocumentVectors = {
}
},
+ where: async function (clause = {}, limit) {
+ try {
+ const results = await prisma.document_vectors.findMany({
+ where: clause,
+ take: limit || undefined,
+ });
+ return results;
+ } catch (error) {
+ console.error("Where query failed", error);
+ return [];
+ }
+ },
+
deleteForWorkspace: async function (workspaceId) {
const documents = await Document.forWorkspace(workspaceId);
const docIds = [...new Set(documents.map((doc) => doc.docId))];
@@ -40,27 +53,24 @@ const DocumentVectors = {
}
},
- where: async function (clause = {}, limit) {
+ deleteIds: async function (ids = []) {
try {
- const results = await prisma.document_vectors.findMany({
- where: clause,
- take: limit || undefined,
+ await prisma.document_vectors.deleteMany({
+ where: { id: { in: ids } },
});
- return results;
+ return true;
} catch (error) {
- console.error("Where query failed", error);
- return [];
+ console.error("Delete IDs failed", error);
+ return false;
}
},
- deleteIds: async function (ids = []) {
+ delete: async function (clause = {}) {
try {
- await prisma.document_vectors.deleteMany({
- where: { id: { in: ids } },
- });
+ await prisma.document_vectors.deleteMany({ where: clause });
return true;
} catch (error) {
- console.error("Delete IDs failed", error);
+ console.error("Delete failed", error);
return false;
}
},
diff --git a/server/utils/files/index.js b/server/utils/files/index.js
index 598884f999..625d8582cd 100644
--- a/server/utils/files/index.js
+++ b/server/utils/files/index.js
@@ -281,6 +281,16 @@ async function getWatchedDocumentFilenames(filenames = []) {
}, {});
}
+/**
+ * Purges the entire vector-cache folder and recreates it.
+ * @returns {void}
+ */
+function purgeEntireVectorCache() {
+ fs.rmSync(vectorCachePath, { recursive: true, force: true });
+ fs.mkdirSync(vectorCachePath);
+ return;
+}
+
module.exports = {
findDocumentInDocuments,
cachedVectorInformation,
@@ -293,4 +303,5 @@ module.exports = {
isWithin,
documentsPath,
hasVectorCachedFiles,
+ purgeEntireVectorCache,
};
diff --git a/server/utils/helpers/index.js b/server/utils/helpers/index.js
index e599078b6a..748e4fb1b1 100644
--- a/server/utils/helpers/index.js
+++ b/server/utils/helpers/index.js
@@ -52,10 +52,11 @@
/**
* Gets the systems current vector database provider.
+ * @param {('pinecone' | 'chroma' | 'lancedb' | 'weaviate' | 'qdrant' | 'milvus' | 'zilliz' | 'astra') | null} getExactly - If provided, this will return an explit provider.
* @returns { BaseVectorDatabaseProvider}
*/
-function getVectorDbClass() {
- const vectorSelection = process.env.VECTOR_DB || "lancedb";
+function getVectorDbClass(getExactly = null) {
+ const vectorSelection = getExactly ?? process.env.VECTOR_DB ?? "lancedb";
switch (vectorSelection) {
case "pinecone":
const { Pinecone } = require("../vectorDbProviders/pinecone");
diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js
index 3cfc13e6e1..948703dca2 100644
--- a/server/utils/helpers/updateENV.js
+++ b/server/utils/helpers/updateENV.js
@@ -1,3 +1,5 @@
+const { resetAllVectorStores } = require("../vectorStore/resetAllVectorStores");
+
const KEY_MAPPING = {
LLMProvider: {
envKey: "LLM_PROVIDER",
@@ -248,6 +250,7 @@ const KEY_MAPPING = {
EmbeddingEngine: {
envKey: "EMBEDDING_ENGINE",
checks: [supportedEmbeddingModel],
+ postUpdate: [handleVectorStoreReset],
},
EmbeddingBasePath: {
envKey: "EMBEDDING_BASE_PATH",
@@ -256,6 +259,7 @@ const KEY_MAPPING = {
EmbeddingModelPref: {
envKey: "EMBEDDING_MODEL_PREF",
checks: [isNotEmpty],
+ postUpdate: [handleVectorStoreReset],
},
EmbeddingModelMaxChunkLength: {
envKey: "EMBEDDING_MODEL_MAX_CHUNK_LENGTH",
@@ -276,6 +280,7 @@ const KEY_MAPPING = {
VectorDB: {
envKey: "VECTOR_DB",
checks: [isNotEmpty, supportedVectorDB],
+ postUpdate: [handleVectorStoreReset],
},
// Chroma Options
@@ -878,6 +883,24 @@ function noRestrictedChars(input = "") {
: null;
}
+async function handleVectorStoreReset(key, prevValue, nextValue) {
+ if (prevValue === nextValue) return;
+ if (key === "VectorDB") {
+ console.log(
+ `Vector configuration changed from ${prevValue} to ${nextValue} - resetting ${prevValue} namespaces`
+ );
+ return await resetAllVectorStores({ vectorDbKey: prevValue });
+ }
+
+ if (key === "EmbeddingEngine" || key === "EmbeddingModelPref") {
+ console.log(
+ `${key} changed from ${prevValue} to ${nextValue} - resetting ${process.env.VECTOR_DB} namespaces`
+ );
+ return await resetAllVectorStores({ vectorDbKey: process.env.VECTOR_DB });
+ }
+ return false;
+}
+
// This will force update .env variables which for any which reason were not able to be parsed or
// read from an ENV file as this seems to be a complicating step for many so allowing people to write
// to the process will at least alleviate that issue. It does not perform comprehensive validity checks or sanity checks
diff --git a/server/utils/vectorStore/resetAllVectorStores.js b/server/utils/vectorStore/resetAllVectorStores.js
new file mode 100644
index 0000000000..3bb9a5ec4c
--- /dev/null
+++ b/server/utils/vectorStore/resetAllVectorStores.js
@@ -0,0 +1,48 @@
+const { Workspace } = require("../../models/workspace");
+const { Document } = require("../../models/documents");
+const { DocumentVectors } = require("../../models/vectors");
+const { EventLogs } = require("../../models/eventLogs");
+const { purgeEntireVectorCache } = require("../files");
+const { getVectorDbClass } = require("../helpers");
+
+/**
+ * Resets all vector database and associated content:
+ * - Purges the entire vector-cache folder.
+ * - Deletes all document vectors from the database.
+ * - Deletes all documents from the database.
+ * - Deletes all vector db namespaces for each workspace.
+ * - Logs an event indicating the reset.
+ * @param {string} vectorDbKey - The _previous_ vector database provider name that we will be resetting.
+ * @returns {Promise} - True if successful, false otherwise.
+ */
+async function resetAllVectorStores({ vectorDbKey }) {
+ try {
+ const workspaces = await Workspace.where();
+ purgeEntireVectorCache(); // Purges the entire vector-cache folder.
+ await DocumentVectors.delete(); // Deletes all document vectors from the database.
+ await Document.delete(); // Deletes all documents from the database.
+ await EventLogs.logEvent("workspace_vectors_reset", {
+ reason: "System vector configuration changed",
+ });
+
+ console.log(
+ "Resetting anythingllm managed vector namespaces for",
+ vectorDbKey
+ );
+ const VectorDb = getVectorDbClass(vectorDbKey);
+ for (const workspace of workspaces) {
+ try {
+ await VectorDb["delete-namespace"]({ namespace: workspace.slug });
+ } catch (e) {
+ console.error(e.message);
+ }
+ }
+
+ return true;
+ } catch (error) {
+ console.error("Failed to reset vector stores:", error);
+ return false;
+ }
+}
+
+module.exports = { resetAllVectorStores };