diff --git a/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx b/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx
index ad7c08d35..b3ecab4b1 100644
--- a/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx
+++ b/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx
@@ -21,10 +21,50 @@ import { useModal } from "@/hooks/useModal";
import ModalWrapper from "@/components/ModalWrapper";
import CTAButton from "@/components/lib/CTAButton";
+const EMBEDDERS = [
+ {
+ name: "AnythingLLM Embedder",
+ value: "native",
+ logo: AnythingLLMIcon,
+ options: (settings) => ,
+ description:
+ "Use the built-in embedding engine for AnythingLLM. Zero setup!",
+ },
+ {
+ name: "OpenAI",
+ value: "openai",
+ logo: OpenAiLogo,
+ options: (settings) => ,
+ description: "The standard option for most non-commercial use.",
+ },
+ {
+ name: "Azure OpenAI",
+ value: "azure",
+ logo: AzureOpenAiLogo,
+ options: (settings) => ,
+ description: "The enterprise option of OpenAI hosted on Azure services.",
+ },
+ {
+ name: "Local AI",
+ value: "localai",
+ logo: LocalAiLogo,
+ options: (settings) => ,
+ description: "Run embedding models locally on your own machine.",
+ },
+ {
+ name: "Ollama",
+ value: "ollama",
+ logo: OllamaLogo,
+ options: (settings) => ,
+ description: "Run embedding models locally on your own machine.",
+ },
+];
+
export default function GeneralEmbeddingPreference() {
const [saving, setSaving] = useState(false);
const [hasChanges, setHasChanges] = useState(false);
const [hasEmbeddings, setHasEmbeddings] = useState(false);
+ const [hasCachedEmbeddings, setHasCachedEmbeddings] = useState(false);
const [settings, setSettings] = useState(null);
const [loading, setLoading] = useState(true);
const [searchQuery, setSearchQuery] = useState("");
@@ -34,12 +74,24 @@ export default function GeneralEmbeddingPreference() {
const searchInputRef = useRef(null);
const { isOpen, openModal, closeModal } = useModal();
+ function embedderModelChanged(formEl) {
+ try {
+ const newModel = new FormData(formEl).get("EmbeddingModelPref") ?? null;
+ if (newModel === null) return false;
+ return settings?.EmbeddingModelPref !== newModel;
+ } catch (error) {
+ console.error(error);
+ }
+ return false;
+ }
+
const handleSubmit = async (e) => {
e.preventDefault();
if (
- selectedEmbedder !== settings?.EmbeddingEngine &&
+ (selectedEmbedder !== settings?.EmbeddingEngine ||
+ embedderModelChanged(e.target)) &&
hasChanges &&
- hasEmbeddings
+ (hasEmbeddings || hasCachedEmbeddings)
) {
openModal();
} else {
@@ -89,50 +141,12 @@ export default function GeneralEmbeddingPreference() {
setSettings(_settings);
setSelectedEmbedder(_settings?.EmbeddingEngine || "native");
setHasEmbeddings(_settings?.HasExistingEmbeddings || false);
+ setHasCachedEmbeddings(_settings?.HasCachedEmbeddings || false);
setLoading(false);
}
fetchKeys();
}, []);
- const EMBEDDERS = [
- {
- name: "AnythingLLM Embedder",
- value: "native",
- logo: AnythingLLMIcon,
- options: ,
- description:
- "Use the built-in embedding engine for AnythingLLM. Zero setup!",
- },
- {
- name: "OpenAI",
- value: "openai",
- logo: OpenAiLogo,
- options: ,
- description: "The standard option for most non-commercial use.",
- },
- {
- name: "Azure OpenAI",
- value: "azure",
- logo: AzureOpenAiLogo,
- options: ,
- description: "The enterprise option of OpenAI hosted on Azure services.",
- },
- {
- name: "Local AI",
- value: "localai",
- logo: LocalAiLogo,
- options: ,
- description: "Run embedding models locally on your own machine.",
- },
- {
- name: "Ollama",
- value: "ollama",
- logo: OllamaLogo,
- options: ,
- description: "Run embedding models locally on your own machine.",
- },
- ];
-
useEffect(() => {
const filtered = EMBEDDERS.filter((embedder) =>
embedder.name.toLowerCase().includes(searchQuery.toLowerCase())
@@ -282,7 +296,7 @@ export default function GeneralEmbeddingPreference() {
{selectedEmbedder &&
EMBEDDERS.find(
(embedder) => embedder.value === selectedEmbedder
- )?.options}
+ )?.options(settings)}
@@ -290,7 +304,7 @@ export default function GeneralEmbeddingPreference() {
)}
diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js
index a6a7e50f0..20c161cd5 100644
--- a/server/models/systemSettings.js
+++ b/server/models/systemSettings.js
@@ -87,6 +87,7 @@ const SystemSettings = {
},
},
currentSettings: async function () {
+ const { hasVectorCachedFiles } = require("../utils/files");
const llmProvider = process.env.LLM_PROVIDER;
const vectorDB = process.env.VECTOR_DB;
return {
@@ -104,7 +105,8 @@ const SystemSettings = {
// Embedder Provider Selection Settings & Configs
// --------------------------------------------------------
EmbeddingEngine: process.env.EMBEDDING_ENGINE,
- HasExistingEmbeddings: await this.hasEmbeddings(),
+ HasExistingEmbeddings: await this.hasEmbeddings(), // check if they have any currently embedded documents active in workspaces.
+ HasCachedEmbeddings: hasVectorCachedFiles(), // check if they any currently cached embedded docs.
EmbeddingBasePath: process.env.EMBEDDING_BASE_PATH,
EmbeddingModelPref: process.env.EMBEDDING_MODEL_PREF,
EmbeddingModelMaxChunkLength:
diff --git a/server/utils/files/index.js b/server/utils/files/index.js
index 83dd229cc..fea6f7f7e 100644
--- a/server/utils/files/index.js
+++ b/server/utils/files/index.js
@@ -192,6 +192,19 @@ function normalizePath(filepath = "") {
return result;
}
+// Check if the vector-cache folder is empty or not
+// useful for it the user is changing embedders as this will
+// break the previous cache.
+function hasVectorCachedFiles() {
+ try {
+ return (
+ fs.readdirSync(vectorCachePath)?.filter((name) => name.endsWith(".json"))
+ .length !== 0
+ );
+ } catch {}
+ return false;
+}
+
module.exports = {
findDocumentInDocuments,
cachedVectorInformation,
@@ -203,4 +216,5 @@ module.exports = {
normalizePath,
isWithin,
documentsPath,
+ hasVectorCachedFiles,
};