diff --git a/frontend/src/components/LLMSelection/AnthropicAiOptions/index.jsx b/frontend/src/components/LLMSelection/AnthropicAiOptions/index.jsx
index e8c288d60da87539500210ab4f305e6a3d06a32b..9fe283ffe0e0b12f62005c80c0dde14263a25e76 100644
--- a/frontend/src/components/LLMSelection/AnthropicAiOptions/index.jsx
+++ b/frontend/src/components/LLMSelection/AnthropicAiOptions/index.jsx
@@ -1,26 +1,6 @@
-import { Info } from "@phosphor-icons/react";
-import paths from "@/utils/paths";
-
-export default function AnthropicAiOptions({ settings, showAlert = false }) {
+export default function AnthropicAiOptions({ settings }) {
   return (
     <div className="w-full flex flex-col">
-      {showAlert && (
-        <div className="flex flex-col md:flex-row md:items-center gap-x-2 text-white mb-6 bg-blue-800/30 w-fit rounded-lg px-4 py-2">
-          <div className="gap-x-2 flex items-center">
-            <Info size={12} className="hidden md:visible" />
-            <p className="text-sm md:text-base">
-              Anthropic as your LLM requires you to set an embedding service to
-              use.
-            </p>
-          </div>
-          <a
-            href={paths.settings.embeddingPreference()}
-            className="text-sm md:text-base my-2 underline"
-          >
-            Manage embedding &rarr;
-          </a>
-        </div>
-      )}
       <div className="w-full flex items-center gap-4">
         <div className="flex flex-col w-60">
           <label className="text-white text-sm font-semibold block mb-4">
@@ -38,32 +18,34 @@ export default function AnthropicAiOptions({ settings, showAlert = false }) {
           />
         </div>
 
-        <div className="flex flex-col w-60">
-          <label className="text-white text-sm font-semibold block mb-4">
-            Chat Model Selection
-          </label>
-          <select
-            name="AnthropicModelPref"
-            defaultValue={settings?.AnthropicModelPref || "claude-2"}
-            required={true}
-            className="bg-zinc-900 border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
-          >
-            {[
-              "claude-instant-1.2",
-              "claude-2.0",
-              "claude-2.1",
-              "claude-3-haiku-20240307",
-              "claude-3-opus-20240229",
-              "claude-3-sonnet-20240229",
-            ].map((model) => {
-              return (
-                <option key={model} value={model}>
-                  {model}
-                </option>
-              );
-            })}
-          </select>
-        </div>
+        {!settings?.credentialsOnly && (
+          <div className="flex flex-col w-60">
+            <label className="text-white text-sm font-semibold block mb-4">
+              Chat Model Selection
+            </label>
+            <select
+              name="AnthropicModelPref"
+              defaultValue={settings?.AnthropicModelPref || "claude-2"}
+              required={true}
+              className="bg-zinc-900 border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
+            >
+              {[
+                "claude-instant-1.2",
+                "claude-2.0",
+                "claude-2.1",
+                "claude-3-haiku-20240307",
+                "claude-3-opus-20240229",
+                "claude-3-sonnet-20240229",
+              ].map((model) => {
+                return (
+                  <option key={model} value={model}>
+                    {model}
+                  </option>
+                );
+              })}
+            </select>
+          </div>
+        )}
       </div>
     </div>
   );
diff --git a/frontend/src/components/LLMSelection/GeminiLLMOptions/index.jsx b/frontend/src/components/LLMSelection/GeminiLLMOptions/index.jsx
index 3b53ccc1e4a26af8db4d5200654471cff905b901..a46e5132933783035e590c4e2d47add21247271f 100644
--- a/frontend/src/components/LLMSelection/GeminiLLMOptions/index.jsx
+++ b/frontend/src/components/LLMSelection/GeminiLLMOptions/index.jsx
@@ -18,25 +18,27 @@ export default function GeminiLLMOptions({ settings }) {
           />
         </div>
 
-        <div className="flex flex-col w-60">
-          <label className="text-white text-sm font-semibold block mb-4">
-            Chat Model Selection
-          </label>
-          <select
-            name="GeminiLLMModelPref"
-            defaultValue={settings?.GeminiLLMModelPref || "gemini-pro"}
-            required={true}
-            className="bg-zinc-900 border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
-          >
-            {["gemini-pro"].map((model) => {
-              return (
-                <option key={model} value={model}>
-                  {model}
-                </option>
-              );
-            })}
-          </select>
-        </div>
+        {!settings?.credentialsOnly && (
+          <div className="flex flex-col w-60">
+            <label className="text-white text-sm font-semibold block mb-4">
+              Chat Model Selection
+            </label>
+            <select
+              name="GeminiLLMModelPref"
+              defaultValue={settings?.GeminiLLMModelPref || "gemini-pro"}
+              required={true}
+              className="bg-zinc-900 border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
+            >
+              {["gemini-pro"].map((model) => {
+                return (
+                  <option key={model} value={model}>
+                    {model}
+                  </option>
+                );
+              })}
+            </select>
+          </div>
+        )}
       </div>
     </div>
   );
diff --git a/frontend/src/components/LLMSelection/GroqAiOptions/index.jsx b/frontend/src/components/LLMSelection/GroqAiOptions/index.jsx
index cc6fbbcc061960609ef79e6e8108d0264150709c..c85f0f1e018009d95578b5a5995c9314cef8698e 100644
--- a/frontend/src/components/LLMSelection/GroqAiOptions/index.jsx
+++ b/frontend/src/components/LLMSelection/GroqAiOptions/index.jsx
@@ -17,25 +17,27 @@ export default function GroqAiOptions({ settings }) {
         />
       </div>
 
-      <div className="flex flex-col w-60">
-        <label className="text-white text-sm font-semibold block mb-4">
-          Chat Model Selection
-        </label>
-        <select
-          name="GroqModelPref"
-          defaultValue={settings?.GroqModelPref || "llama2-70b-4096"}
-          required={true}
-          className="bg-zinc-900 border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
-        >
-          {["llama2-70b-4096", "mixtral-8x7b-32768"].map((model) => {
-            return (
-              <option key={model} value={model}>
-                {model}
-              </option>
-            );
-          })}
-        </select>
-      </div>
+      {!settings?.credentialsOnly && (
+        <div className="flex flex-col w-60">
+          <label className="text-white text-sm font-semibold block mb-4">
+            Chat Model Selection
+          </label>
+          <select
+            name="GroqModelPref"
+            defaultValue={settings?.GroqModelPref || "llama2-70b-4096"}
+            required={true}
+            className="bg-zinc-900 border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
+          >
+            {["llama2-70b-4096", "mixtral-8x7b-32768"].map((model) => {
+              return (
+                <option key={model} value={model}>
+                  {model}
+                </option>
+              );
+            })}
+          </select>
+        </div>
+      )}
     </div>
   );
 }
diff --git a/frontend/src/components/LLMSelection/LMStudioOptions/index.jsx b/frontend/src/components/LLMSelection/LMStudioOptions/index.jsx
index 200c77a6e6628f4c422ec3b52dd78df4f3bb7dee..c94a99d7871f9e61ee4f8efa686df4b6140f6217 100644
--- a/frontend/src/components/LLMSelection/LMStudioOptions/index.jsx
+++ b/frontend/src/components/LLMSelection/LMStudioOptions/index.jsx
@@ -46,23 +46,27 @@ export default function LMStudioOptions({ settings, showAlert = false }) {
             onBlur={() => setBasePath(basePathValue)}
           />
         </div>
-        <LMStudioModelSelection settings={settings} basePath={basePath} />
-        <div className="flex flex-col w-60">
-          <label className="text-white text-sm font-semibold block mb-4">
-            Token context window
-          </label>
-          <input
-            type="number"
-            name="LMStudioTokenLimit"
-            className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
-            placeholder="4096"
-            min={1}
-            onScroll={(e) => e.target.blur()}
-            defaultValue={settings?.LMStudioTokenLimit}
-            required={true}
-            autoComplete="off"
-          />
-        </div>
+        {!settings?.credentialsOnly && (
+          <>
+            <LMStudioModelSelection settings={settings} basePath={basePath} />
+            <div className="flex flex-col w-60">
+              <label className="text-white text-sm font-semibold block mb-4">
+                Token context window
+              </label>
+              <input
+                type="number"
+                name="LMStudioTokenLimit"
+                className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
+                placeholder="4096"
+                min={1}
+                onScroll={(e) => e.target.blur()}
+                defaultValue={settings?.LMStudioTokenLimit}
+                required={true}
+                autoComplete="off"
+              />
+            </div>
+          </>
+        )}
       </div>
     </div>
   );
diff --git a/frontend/src/components/LLMSelection/LocalAiOptions/index.jsx b/frontend/src/components/LLMSelection/LocalAiOptions/index.jsx
index 91e3867027ba20182b52e94712f66549b7fa4429..36b2f2588ecc41a861bee1f0c58163007445b6d4 100644
--- a/frontend/src/components/LLMSelection/LocalAiOptions/index.jsx
+++ b/frontend/src/components/LLMSelection/LocalAiOptions/index.jsx
@@ -46,27 +46,31 @@ export default function LocalAiOptions({ settings, showAlert = false }) {
             onBlur={() => setBasePath(basePathValue)}
           />
         </div>
-        <LocalAIModelSelection
-          settings={settings}
-          basePath={basePath}
-          apiKey={apiKey}
-        />
-        <div className="flex flex-col w-60">
-          <label className="text-white text-sm font-semibold block mb-4">
-            Token context window
-          </label>
-          <input
-            type="number"
-            name="LocalAiTokenLimit"
-            className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
-            placeholder="4096"
-            min={1}
-            onScroll={(e) => e.target.blur()}
-            defaultValue={settings?.LocalAiTokenLimit}
-            required={true}
-            autoComplete="off"
-          />
-        </div>
+        {!settings?.credentialsOnly && (
+          <>
+            <LocalAIModelSelection
+              settings={settings}
+              basePath={basePath}
+              apiKey={apiKey}
+            />
+            <div className="flex flex-col w-60">
+              <label className="text-white text-sm font-semibold block mb-4">
+                Token context window
+              </label>
+              <input
+                type="number"
+                name="LocalAiTokenLimit"
+                className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
+                placeholder="4096"
+                min={1}
+                onScroll={(e) => e.target.blur()}
+                defaultValue={settings?.LocalAiTokenLimit}
+                required={true}
+                autoComplete="off"
+              />
+            </div>
+          </>
+        )}
       </div>
       <div className="w-full flex items-center gap-4">
         <div className="flex flex-col w-60">
diff --git a/frontend/src/components/LLMSelection/MistralOptions/index.jsx b/frontend/src/components/LLMSelection/MistralOptions/index.jsx
index a143436ee7f54f6cd5d4f0deb13ea4e64c0d35dc..4daadcff15d38cb32596926a34ab87088a75d8f6 100644
--- a/frontend/src/components/LLMSelection/MistralOptions/index.jsx
+++ b/frontend/src/components/LLMSelection/MistralOptions/index.jsx
@@ -24,7 +24,9 @@ export default function MistralOptions({ settings }) {
           onBlur={() => setMistralKey(inputValue)}
         />
       </div>
-      <MistralModelSelection settings={settings} apiKey={mistralKey} />
+      {!settings?.credentialsOnly && (
+        <MistralModelSelection settings={settings} apiKey={mistralKey} />
+      )}
     </div>
   );
 }
diff --git a/frontend/src/components/LLMSelection/OllamaLLMOptions/index.jsx b/frontend/src/components/LLMSelection/OllamaLLMOptions/index.jsx
index ddfd7a81b3f84e871e3d23ed94db1df9f239ea37..b08f29447c4b3a1b8958c200701788b140428820 100644
--- a/frontend/src/components/LLMSelection/OllamaLLMOptions/index.jsx
+++ b/frontend/src/components/LLMSelection/OllamaLLMOptions/index.jsx
@@ -27,23 +27,27 @@ export default function OllamaLLMOptions({ settings }) {
             onBlur={() => setBasePath(basePathValue)}
           />
         </div>
-        <OllamaLLMModelSelection settings={settings} basePath={basePath} />
-        <div className="flex flex-col w-60">
-          <label className="text-white text-sm font-semibold block mb-4">
-            Token context window
-          </label>
-          <input
-            type="number"
-            name="OllamaLLMTokenLimit"
-            className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
-            placeholder="4096"
-            min={1}
-            onScroll={(e) => e.target.blur()}
-            defaultValue={settings?.OllamaLLMTokenLimit}
-            required={true}
-            autoComplete="off"
-          />
-        </div>
+        {!settings?.credentialsOnly && (
+          <>
+            <OllamaLLMModelSelection settings={settings} basePath={basePath} />
+            <div className="flex flex-col w-60">
+              <label className="text-white text-sm font-semibold block mb-4">
+                Token context window
+              </label>
+              <input
+                type="number"
+                name="OllamaLLMTokenLimit"
+                className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
+                placeholder="4096"
+                min={1}
+                onScroll={(e) => e.target.blur()}
+                defaultValue={settings?.OllamaLLMTokenLimit}
+                required={true}
+                autoComplete="off"
+              />
+            </div>
+          </>
+        )}
       </div>
     </div>
   );
diff --git a/frontend/src/components/LLMSelection/OpenAiOptions/index.jsx b/frontend/src/components/LLMSelection/OpenAiOptions/index.jsx
index 1e34930961e575e3fceda6019e7722a9c4aaf65f..c5ec337d0a899e4aac4bda13256eae4b6b72d515 100644
--- a/frontend/src/components/LLMSelection/OpenAiOptions/index.jsx
+++ b/frontend/src/components/LLMSelection/OpenAiOptions/index.jsx
@@ -24,7 +24,9 @@ export default function OpenAiOptions({ settings }) {
           onBlur={() => setOpenAIKey(inputValue)}
         />
       </div>
-      <OpenAIModelSelection settings={settings} apiKey={openAIKey} />
+      {!settings?.credentialsOnly && (
+        <OpenAIModelSelection settings={settings} apiKey={openAIKey} />
+      )}
     </div>
   );
 }
diff --git a/frontend/src/components/LLMSelection/OpenRouterOptions/index.jsx b/frontend/src/components/LLMSelection/OpenRouterOptions/index.jsx
index ff2a1d8f076eeb68e4eeca71472c6179d08d085c..94ae320a27ccae0b2e35221ceb8593c99e52538b 100644
--- a/frontend/src/components/LLMSelection/OpenRouterOptions/index.jsx
+++ b/frontend/src/components/LLMSelection/OpenRouterOptions/index.jsx
@@ -19,7 +19,9 @@ export default function OpenRouterOptions({ settings }) {
           spellCheck={false}
         />
       </div>
-      <OpenRouterModelSelection settings={settings} />
+      {!settings?.credentialsOnly && (
+        <OpenRouterModelSelection settings={settings} />
+      )}
     </div>
   );
 }
@@ -84,7 +86,7 @@ function OpenRouterModelSelection({ settings }) {
                 <option
                   key={model.id}
                   value={model.id}
-                  selected={settings.OpenRouterModelPref === model.id}
+                  selected={settings?.OpenRouterModelPref === model.id}
                 >
                   {model.name}
                 </option>
diff --git a/frontend/src/components/LLMSelection/PerplexityOptions/index.jsx b/frontend/src/components/LLMSelection/PerplexityOptions/index.jsx
index 6c45224952692bf3de1fbd21c173ee4b9a39f718..9b53cd1919be6ba4b225d5b2283889775b02e31f 100644
--- a/frontend/src/components/LLMSelection/PerplexityOptions/index.jsx
+++ b/frontend/src/components/LLMSelection/PerplexityOptions/index.jsx
@@ -19,7 +19,9 @@ export default function PerplexityOptions({ settings }) {
           spellCheck={false}
         />
       </div>
-      <PerplexityModelSelection settings={settings} />
+      {!settings?.credentialsOnly && (
+        <PerplexityModelSelection settings={settings} />
+      )}
     </div>
   );
 }
diff --git a/frontend/src/components/LLMSelection/TogetherAiOptions/index.jsx b/frontend/src/components/LLMSelection/TogetherAiOptions/index.jsx
index 2c816339fbf7ea3473aaa302cf116840ed494b40..a0eefc83a920af37b186f678de685f844bcc1f1c 100644
--- a/frontend/src/components/LLMSelection/TogetherAiOptions/index.jsx
+++ b/frontend/src/components/LLMSelection/TogetherAiOptions/index.jsx
@@ -19,7 +19,9 @@ export default function TogetherAiOptions({ settings }) {
           spellCheck={false}
         />
       </div>
-      <TogetherAiModelSelection settings={settings} />
+      {!settings?.credentialsOnly && (
+        <TogetherAiModelSelection settings={settings} />
+      )}
     </div>
   );
 }
@@ -84,7 +86,7 @@ function TogetherAiModelSelection({ settings }) {
                 <option
                   key={model.id}
                   value={model.id}
-                  selected={settings.OpenRouterModelPref === model.id}
+                  selected={settings?.OpenRouterModelPref === model.id}
                 >
                   {model.name}
                 </option>
diff --git a/frontend/src/hooks/useGetProvidersModels.js b/frontend/src/hooks/useGetProvidersModels.js
index f578c929f362a8732ede786447bd48118b8cb44d..95df82a3a9821bd82dcaca0978bf3e52c607c12b 100644
--- a/frontend/src/hooks/useGetProvidersModels.js
+++ b/frontend/src/hooks/useGetProvidersModels.js
@@ -2,7 +2,7 @@ import System from "@/models/system";
 import { useEffect, useState } from "react";
 
 // Providers which cannot use this feature for workspace<>model selection
-export const DISABLED_PROVIDERS = ["azure", "lmstudio"];
+export const DISABLED_PROVIDERS = ["azure", "lmstudio", "native"];
 const PROVIDER_DEFAULT_MODELS = {
   openai: [
     "gpt-3.5-turbo",
diff --git a/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx b/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx
index b9525c925610bcc920d42fb2c3de3160212b04cf..ccc6508ba5a86911144b52eb20e517996fdb4394 100644
--- a/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx
+++ b/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx
@@ -36,6 +36,130 @@ import GroqAiOptions from "@/components/LLMSelection/GroqAiOptions";
 import LLMItem from "@/components/LLMSelection/LLMItem";
 import { CaretUpDown, MagnifyingGlass, X } from "@phosphor-icons/react";
 
+export const AVAILABLE_LLM_PROVIDERS = [
+  {
+    name: "OpenAI",
+    value: "openai",
+    logo: OpenAiLogo,
+    options: (settings) => <OpenAiOptions settings={settings} />,
+    description: "The standard option for most non-commercial use.",
+    requiredConfig: ["OpenAiKey"],
+  },
+  {
+    name: "Azure OpenAI",
+    value: "azure",
+    logo: AzureOpenAiLogo,
+    options: (settings) => <AzureAiOptions settings={settings} />,
+    description: "The enterprise option of OpenAI hosted on Azure services.",
+    requiredConfig: ["AzureOpenAiEndpoint"],
+  },
+  {
+    name: "Anthropic",
+    value: "anthropic",
+    logo: AnthropicLogo,
+    options: (settings) => <AnthropicAiOptions settings={settings} />,
+    description: "A friendly AI Assistant hosted by Anthropic.",
+    requiredConfig: ["AnthropicApiKey"],
+  },
+  {
+    name: "Gemini",
+    value: "gemini",
+    logo: GeminiLogo,
+    options: (settings) => <GeminiLLMOptions settings={settings} />,
+    description: "Google's largest and most capable AI model",
+    requiredConfig: ["GeminiLLMApiKey"],
+  },
+  {
+    name: "HuggingFace",
+    value: "huggingface",
+    logo: HuggingFaceLogo,
+    options: (settings) => <HuggingFaceOptions settings={settings} />,
+    description:
+      "Access 150,000+ open-source LLMs and the world's AI community",
+    requiredConfig: [
+      "HuggingFaceLLMEndpoint",
+      "HuggingFaceLLMAccessToken",
+      "HuggingFaceLLMTokenLimit",
+    ],
+  },
+  {
+    name: "Ollama",
+    value: "ollama",
+    logo: OllamaLogo,
+    options: (settings) => <OllamaLLMOptions settings={settings} />,
+    description: "Run LLMs locally on your own machine.",
+    requiredConfig: ["OllamaLLMBasePath"],
+  },
+  {
+    name: "LM Studio",
+    value: "lmstudio",
+    logo: LMStudioLogo,
+    options: (settings) => <LMStudioOptions settings={settings} />,
+    description:
+      "Discover, download, and run thousands of cutting edge LLMs in a few clicks.",
+    requiredConfig: ["LMStudioBasePath"],
+  },
+  {
+    name: "Local AI",
+    value: "localai",
+    logo: LocalAiLogo,
+    options: (settings) => <LocalAiOptions settings={settings} />,
+    description: "Run LLMs locally on your own machine.",
+    requiredConfig: ["LocalAiApiKey", "LocalAiBasePath", "LocalAiTokenLimit"],
+  },
+  {
+    name: "Together AI",
+    value: "togetherai",
+    logo: TogetherAILogo,
+    options: (settings) => <TogetherAiOptions settings={settings} />,
+    description: "Run open source models from Together AI.",
+    requiredConfig: ["TogetherAiApiKey"],
+  },
+  {
+    name: "Mistral",
+    value: "mistral",
+    logo: MistralLogo,
+    options: (settings) => <MistralOptions settings={settings} />,
+    description: "Run open source models from Mistral AI.",
+    requiredConfig: ["MistralApiKey"],
+  },
+  {
+    name: "Perplexity AI",
+    value: "perplexity",
+    logo: PerplexityLogo,
+    options: (settings) => <PerplexityOptions settings={settings} />,
+    description:
+      "Run powerful and internet-connected models hosted by Perplexity AI.",
+    requiredConfig: ["PerplexityApiKey"],
+  },
+  {
+    name: "OpenRouter",
+    value: "openrouter",
+    logo: OpenRouterLogo,
+    options: (settings) => <OpenRouterOptions settings={settings} />,
+    description: "A unified interface for LLMs.",
+    requiredConfig: ["OpenRouterApiKey"],
+  },
+  {
+    name: "Groq",
+    value: "groq",
+    logo: GroqLogo,
+    options: (settings) => <GroqAiOptions settings={settings} />,
+    description:
+      "The fastest LLM inferencing available for real-time AI applications.",
+    requiredConfig: ["GroqApiKey"],
+  },
+  {
+    name: "Native",
+    value: "native",
+    logo: AnythingLLMIcon,
+    options: (settings) => <NativeLLMOptions settings={settings} />,
+    description:
+      "Use a downloaded custom Llama model for chatting on this AnythingLLM instance.",
+    requiredConfig: [],
+  },
+];
+
 export default function GeneralLLMPreference() {
   const [saving, setSaving] = useState(false);
   const [hasChanges, setHasChanges] = useState(false);
@@ -94,120 +218,15 @@ export default function GeneralLLMPreference() {
   }, []);
 
   useEffect(() => {
-    const filtered = LLMS.filter((llm) =>
+    const filtered = AVAILABLE_LLM_PROVIDERS.filter((llm) =>
       llm.name.toLowerCase().includes(searchQuery.toLowerCase())
     );
     setFilteredLLMs(filtered);
   }, [searchQuery, selectedLLM]);
 
-  const LLMS = [
-    {
-      name: "OpenAI",
-      value: "openai",
-      logo: OpenAiLogo,
-      options: <OpenAiOptions settings={settings} />,
-      description: "The standard option for most non-commercial use.",
-    },
-    {
-      name: "Azure OpenAI",
-      value: "azure",
-      logo: AzureOpenAiLogo,
-      options: <AzureAiOptions settings={settings} />,
-      description: "The enterprise option of OpenAI hosted on Azure services.",
-    },
-    {
-      name: "Anthropic",
-      value: "anthropic",
-      logo: AnthropicLogo,
-      options: <AnthropicAiOptions settings={settings} />,
-      description: "A friendly AI Assistant hosted by Anthropic.",
-    },
-    {
-      name: "Gemini",
-      value: "gemini",
-      logo: GeminiLogo,
-      options: <GeminiLLMOptions settings={settings} />,
-      description: "Google's largest and most capable AI model",
-    },
-    {
-      name: "HuggingFace",
-      value: "huggingface",
-      logo: HuggingFaceLogo,
-      options: <HuggingFaceOptions settings={settings} />,
-      description:
-        "Access 150,000+ open-source LLMs and the world's AI community",
-    },
-    {
-      name: "Ollama",
-      value: "ollama",
-      logo: OllamaLogo,
-      options: <OllamaLLMOptions settings={settings} />,
-      description: "Run LLMs locally on your own machine.",
-    },
-    {
-      name: "LM Studio",
-      value: "lmstudio",
-      logo: LMStudioLogo,
-      options: <LMStudioOptions settings={settings} />,
-      description:
-        "Discover, download, and run thousands of cutting edge LLMs in a few clicks.",
-    },
-    {
-      name: "Local AI",
-      value: "localai",
-      logo: LocalAiLogo,
-      options: <LocalAiOptions settings={settings} />,
-      description: "Run LLMs locally on your own machine.",
-    },
-    {
-      name: "Together AI",
-      value: "togetherai",
-      logo: TogetherAILogo,
-      options: <TogetherAiOptions settings={settings} />,
-      description: "Run open source models from Together AI.",
-    },
-    {
-      name: "Mistral",
-      value: "mistral",
-      logo: MistralLogo,
-      options: <MistralOptions settings={settings} />,
-      description: "Run open source models from Mistral AI.",
-    },
-    {
-      name: "Perplexity AI",
-      value: "perplexity",
-      logo: PerplexityLogo,
-      options: <PerplexityOptions settings={settings} />,
-      description:
-        "Run powerful and internet-connected models hosted by Perplexity AI.",
-    },
-    {
-      name: "OpenRouter",
-      value: "openrouter",
-      logo: OpenRouterLogo,
-      options: <OpenRouterOptions settings={settings} />,
-      description: "A unified interface for LLMs.",
-    },
-    {
-      name: "Groq",
-      value: "groq",
-      logo: GroqLogo,
-      options: <GroqAiOptions settings={settings} />,
-      description:
-        "The fastest LLM inferencing available for real-time AI applications.",
-    },
-    {
-      name: "Native",
-      value: "native",
-      logo: AnythingLLMIcon,
-      options: <NativeLLMOptions settings={settings} />,
-      description:
-        "Use a downloaded custom Llama model for chatting on this AnythingLLM instance.",
-    },
-  ];
-
-  const selectedLLMObject = LLMS.find((llm) => llm.value === selectedLLM);
-
+  const selectedLLMObject = AVAILABLE_LLM_PROVIDERS.find(
+    (llm) => llm.value === selectedLLM
+  );
   return (
     <div className="w-screen h-screen overflow-hidden bg-sidebar flex">
       <Sidebar />
@@ -339,7 +358,9 @@ export default function GeneralLLMPreference() {
                 className="mt-4 flex flex-col gap-y-1"
               >
                 {selectedLLM &&
-                  LLMS.find((llm) => llm.value === selectedLLM)?.options}
+                  AVAILABLE_LLM_PROVIDERS.find(
+                    (llm) => llm.value === selectedLLM
+                  )?.options?.(settings)}
               </div>
             </div>
           </form>
diff --git a/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatModelSelection/index.jsx b/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatModelSelection/index.jsx
index 3ef7bb7aca164367408a68590cdb59d377278e59..9ed424294982fbe02ff7b702191c83b18d095cb4 100644
--- a/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatModelSelection/index.jsx
+++ b/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatModelSelection/index.jsx
@@ -3,21 +3,20 @@ import useGetProviderModels, {
 } from "@/hooks/useGetProvidersModels";
 
 export default function ChatModelSelection({
-  settings,
+  provider,
   workspace,
   setHasChanges,
 }) {
-  const { defaultModels, customModels, loading } = useGetProviderModels(
-    settings?.LLMProvider
-  );
-  if (DISABLED_PROVIDERS.includes(settings?.LLMProvider)) return null;
+  const { defaultModels, customModels, loading } =
+    useGetProviderModels(provider);
+  if (DISABLED_PROVIDERS.includes(provider)) return null;
 
   if (loading) {
     return (
       <div>
         <div className="flex flex-col">
           <label htmlFor="name" className="block input-label">
-            Chat model
+            Workspace Chat model
           </label>
           <p className="text-white text-opacity-60 text-xs font-medium py-1.5">
             The specific chat model that will be used for this workspace. If
@@ -42,8 +41,7 @@ export default function ChatModelSelection({
     <div>
       <div className="flex flex-col">
         <label htmlFor="name" className="block input-label">
-          Chat model{" "}
-          <span className="font-normal">({settings?.LLMProvider})</span>
+          Workspace Chat model
         </label>
         <p className="text-white text-opacity-60 text-xs font-medium py-1.5">
           The specific chat model that will be used for this workspace. If
@@ -59,9 +57,6 @@ export default function ChatModelSelection({
         }}
         className="bg-zinc-900 text-white text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
       >
-        <option disabled={true} selected={workspace?.chatModel === null}>
-          System default
-        </option>
         {defaultModels.length > 0 && (
           <optgroup label="General models">
             {defaultModels.map((model) => {
diff --git a/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/WorkspaceLLMItem/index.jsx b/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/WorkspaceLLMItem/index.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..872d2a422b09c139f2bfe4cd18ad6ecfa6b1a427
--- /dev/null
+++ b/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/WorkspaceLLMItem/index.jsx
@@ -0,0 +1,151 @@
+// This component differs from the main LLMItem in that it shows if a provider is
+// "ready for use" and if not - will then highjack the click handler to show a modal
+// of the provider options that must be saved to continue.
+import { createPortal } from "react-dom";
+import ModalWrapper from "@/components/ModalWrapper";
+import { useModal } from "@/hooks/useModal";
+import { X } from "@phosphor-icons/react";
+import System from "@/models/system";
+import showToast from "@/utils/toast";
+
+export default function WorkspaceLLM({
+  llm,
+  availableLLMs,
+  settings,
+  checked,
+  onClick,
+}) {
+  const { isOpen, openModal, closeModal } = useModal();
+  const { name, value, logo, description } = llm;
+
+  function handleProviderSelection() {
+    // Determine if provider needs additional setup because its minimum required keys are
+    // not yet set in settings.
+    const requiresAdditionalSetup = (llm.requiredConfig || []).some(
+      (key) => !settings[key]
+    );
+    if (requiresAdditionalSetup) {
+      openModal();
+      return;
+    }
+    onClick(value);
+  }
+
+  return (
+    <>
+      <div
+        onClick={handleProviderSelection}
+        className={`w-full p-2 rounded-md hover:cursor-pointer hover:bg-white/10 ${
+          checked ? "bg-white/10" : ""
+        }`}
+      >
+        <input
+          type="checkbox"
+          value={value}
+          className="peer hidden"
+          checked={checked}
+          readOnly={true}
+          formNoValidate={true}
+        />
+        <div className="flex gap-x-4 items-center">
+          <img
+            src={logo}
+            alt={`${name} logo`}
+            className="w-10 h-10 rounded-md"
+          />
+          <div className="flex flex-col">
+            <div className="text-sm font-semibold text-white">{name}</div>
+            <div className="mt-1 text-xs text-[#D2D5DB]">{description}</div>
+          </div>
+        </div>
+      </div>
+      <SetupProvider
+        availableLLMs={availableLLMs}
+        isOpen={isOpen}
+        provider={value}
+        closeModal={closeModal}
+        postSubmit={onClick}
+      />
+    </>
+  );
+}
+
+function SetupProvider({
+  availableLLMs,
+  isOpen,
+  provider,
+  closeModal,
+  postSubmit,
+}) {
+  if (!isOpen) return null;
+  const LLMOption = availableLLMs.find((llm) => llm.value === provider);
+  if (!LLMOption) return null;
+
+  async function handleUpdate(e) {
+    e.preventDefault();
+    e.stopPropagation();
+    const data = {};
+    const form = new FormData(e.target);
+    for (var [key, value] of form.entries()) data[key] = value;
+    const { error } = await System.updateSystem(data);
+    if (error) {
+      showToast(`Failed to save ${LLMOption.name} settings: ${error}`, "error");
+      return;
+    }
+
+    closeModal();
+    postSubmit();
+    return false;
+  }
+
+  // Cannot do nested forms, it will cause all sorts of issues, so we portal this out
+  // to the parent container form so we don't have nested forms.
+  return createPortal(
+    <ModalWrapper isOpen={isOpen}>
+      <div className="relative w-fit max-w-1/2 max-h-full">
+        <div className="relative bg-main-gradient rounded-xl shadow-[0_4px_14px_rgba(0,0,0,0.25)]">
+          <div className="flex items-start justify-between p-4 border-b rounded-t border-gray-500/50">
+            <h3 className="text-xl font-semibold text-white">
+              Setup {LLMOption.name}
+            </h3>
+            <button
+              onClick={closeModal}
+              type="button"
+              className="transition-all duration-300 text-gray-400 bg-transparent hover:border-white/60 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center bg-sidebar-button hover:bg-menu-item-selected-gradient hover:border-slate-100 hover:border-opacity-50 border-transparent border"
+              data-modal-hide="staticModal"
+            >
+              <X className="text-gray-300 text-lg" />
+            </button>
+          </div>
+
+          <form id="provider-form" onSubmit={handleUpdate}>
+            <div className="py-[17px] px-[20px] flex flex-col gap-y-6">
+              <p className="text-sm text-white">
+                To use {LLMOption.name} as this workspace's LLM you need to set
+                it up first.
+              </p>
+              <div>{LLMOption.options({ credentialsOnly: true })}</div>
+            </div>
+            <div className="flex w-full justify-between items-center p-3 space-x-2 border-t rounded-b border-gray-500/50">
+              <button
+                type="button"
+                onClick={closeModal}
+                className="text-xs px-2 py-1 font-semibold rounded-lg bg-white hover:bg-transparent border-2 border-transparent hover:border-white hover:text-white h-[32px] w-fit -mr-8 whitespace-nowrap shadow-[0_4px_14px_rgba(0,0,0,0.25)]"
+              >
+                Cancel
+              </button>
+              <button
+                type="submit"
+                form="provider-form"
+                className="text-xs px-2 py-1 font-semibold rounded-lg bg-[#46C8FF] hover:bg-[#2C2F36] border-2 border-transparent hover:border-[#46C8FF] hover:text-white h-[32px] w-fit -mr-8 whitespace-nowrap shadow-[0_4px_14px_rgba(0,0,0,0.25)]"
+              >
+                Save {LLMOption.name} settings
+              </button>
+            </div>
+          </form>
+        </div>
+      </div>
+    </ModalWrapper>,
+    document.getElementById("workspace-chat-settings-container")
+  );
+}
diff --git a/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/index.jsx b/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/index.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..07e3559626fe76f397e96cd9010589dece185a8e
--- /dev/null
+++ b/frontend/src/pages/WorkspaceSettings/ChatSettings/WorkspaceLLMSelection/index.jsx
@@ -0,0 +1,159 @@
+import React, { useEffect, useRef, useState } from "react";
+import AnythingLLMIcon from "@/media/logo/anything-llm-icon.png";
+import WorkspaceLLMItem from "./WorkspaceLLMItem";
+import { AVAILABLE_LLM_PROVIDERS } from "@/pages/GeneralSettings/LLMPreference";
+import { CaretUpDown, MagnifyingGlass, X } from "@phosphor-icons/react";
+import ChatModelSelection from "../ChatModelSelection";
+
+const DISABLED_PROVIDERS = ["azure", "lmstudio", "native"];
+const LLM_DEFAULT = {
+  name: "System default",
+  value: "default",
+  logo: AnythingLLMIcon,
+  options: () => <React.Fragment />,
+  description: "Use the system LLM preference for this workspace.",
+  requiredConfig: [],
+};
+
+export default function WorkspaceLLMSelection({
+  settings,
+  workspace,
+  setHasChanges,
+}) {
+  const [filteredLLMs, setFilteredLLMs] = useState([]);
+  const [selectedLLM, setSelectedLLM] = useState(
+    workspace?.chatProvider ?? "default"
+  );
+  const [searchQuery, setSearchQuery] = useState("");
+  const [searchMenuOpen, setSearchMenuOpen] = useState(false);
+  const searchInputRef = useRef(null);
+  const LLMS = [LLM_DEFAULT, ...AVAILABLE_LLM_PROVIDERS].filter(
+    (llm) => !DISABLED_PROVIDERS.includes(llm.value)
+  );
+
+  function updateLLMChoice(selection) {
+    console.log({ selection });
+    setSearchQuery("");
+    setSelectedLLM(selection);
+    setSearchMenuOpen(false);
+    setHasChanges(true);
+  }
+
+  function handleXButton() {
+    if (searchQuery.length > 0) {
+      setSearchQuery("");
+      if (searchInputRef.current) searchInputRef.current.value = "";
+    } else {
+      setSearchMenuOpen(!searchMenuOpen);
+    }
+  }
+
+  useEffect(() => {
+    const filtered = LLMS.filter((llm) =>
+      llm.name.toLowerCase().includes(searchQuery.toLowerCase())
+    );
+    setFilteredLLMs(filtered);
+  }, [LLMS, searchQuery, selectedLLM]);
+
+  const selectedLLMObject = LLMS.find((llm) => llm.value === selectedLLM);
+  return (
+    <div className="border-b border-white/40 pb-8">
+      <div className="flex flex-col">
+        <label htmlFor="name" className="block input-label">
+          Workspace LLM Provider
+        </label>
+        <p className="text-white text-opacity-60 text-xs font-medium py-1.5">
+          The specific LLM provider & model that will be used for this
+          workspace. By default, it uses the system LLM provider and settings.
+        </p>
+      </div>
+
+      <div className="relative">
+        <input type="hidden" name="chatProvider" value={selectedLLM} />
+        {searchMenuOpen && (
+          <div
+            className="fixed top-0 left-0 w-full h-full bg-black bg-opacity-70 backdrop-blur-sm z-10"
+            onClick={() => setSearchMenuOpen(false)}
+          />
+        )}
+        {searchMenuOpen ? (
+          <div className="absolute top-0 left-0 w-full max-w-[640px] max-h-[310px] overflow-auto white-scrollbar min-h-[64px] bg-[#18181B] rounded-lg flex flex-col justify-between cursor-pointer border-2 border-[#46C8FF] z-20">
+            <div className="w-full flex flex-col gap-y-1">
+              <div className="flex items-center sticky top-0 border-b border-[#9CA3AF] mx-4 bg-[#18181B]">
+                <MagnifyingGlass
+                  size={20}
+                  weight="bold"
+                  className="absolute left-4 z-30 text-white -ml-4 my-2"
+                />
+                <input
+                  type="text"
+                  name="llm-search"
+                  autoComplete="off"
+                  placeholder="Search all LLM providers"
+                  className="-ml-4 my-2 bg-transparent z-20 pl-12 h-[38px] w-full px-4 py-1 text-sm outline-none focus:border-white text-white placeholder:text-white placeholder:font-medium"
+                  onChange={(e) => setSearchQuery(e.target.value)}
+                  ref={searchInputRef}
+                  onKeyDown={(e) => {
+                    if (e.key === "Enter") e.preventDefault();
+                  }}
+                />
+                <X
+                  size={20}
+                  weight="bold"
+                  className="cursor-pointer text-white hover:text-[#9CA3AF]"
+                  onClick={handleXButton}
+                />
+              </div>
+              <div className="flex-1 pl-4 pr-2 flex flex-col gap-y-1 overflow-y-auto white-scrollbar pb-4">
+                {filteredLLMs.map((llm) => {
+                  return (
+                    <WorkspaceLLMItem
+                      llm={llm}
+                      key={llm.name}
+                      availableLLMs={LLMS}
+                      settings={settings}
+                      checked={selectedLLM === llm.value}
+                      onClick={() => updateLLMChoice(llm.value)}
+                    />
+                  );
+                })}
+              </div>
+            </div>
+          </div>
+        ) : (
+          <button
+            className="w-full max-w-[640px] h-[64px] bg-[#18181B] rounded-lg flex items-center p-[14px] justify-between cursor-pointer border-2 border-transparent hover:border-[#46C8FF] transition-all duration-300"
+            type="button"
+            onClick={() => setSearchMenuOpen(true)}
+          >
+            <div className="flex gap-x-4 items-center">
+              <img
+                src={selectedLLMObject.logo}
+                alt={`${selectedLLMObject.name} logo`}
+                className="w-10 h-10 rounded-md"
+              />
+              <div className="flex flex-col text-left">
+                <div className="text-sm font-semibold text-white">
+                  {selectedLLMObject.name}
+                </div>
+                <div className="mt-1 text-xs text-[#D2D5DB]">
+                  {selectedLLMObject.description}
+                </div>
+              </div>
+            </div>
+            <CaretUpDown size={24} weight="bold" className="text-white" />
+          </button>
+        )}
+      </div>
+      {selectedLLM !== "default" && (
+        <div className="mt-4 flex flex-col gap-y-1">
+          <ChatModelSelection
+            provider={selectedLLM}
+            workspace={workspace}
+            setHasChanges={setHasChanges}
+          />
+        </div>
+      )}
+    </div>
+  );
+}
diff --git a/frontend/src/pages/WorkspaceSettings/ChatSettings/index.jsx b/frontend/src/pages/WorkspaceSettings/ChatSettings/index.jsx
index 3004b871ce09a376c4a53e1abdc9342f3a5abfe5..a6bab2c37ac2988cc496b9a348033eb10f157c95 100644
--- a/frontend/src/pages/WorkspaceSettings/ChatSettings/index.jsx
+++ b/frontend/src/pages/WorkspaceSettings/ChatSettings/index.jsx
@@ -3,11 +3,11 @@ import Workspace from "@/models/workspace";
 import showToast from "@/utils/toast";
 import { castToType } from "@/utils/types";
 import { useEffect, useRef, useState } from "react";
-import ChatModelSelection from "./ChatModelSelection";
 import ChatHistorySettings from "./ChatHistorySettings";
 import ChatPromptSettings from "./ChatPromptSettings";
 import ChatTemperatureSettings from "./ChatTemperatureSettings";
 import ChatModeSelection from "./ChatModeSelection";
+import WorkspaceLLMSelection from "./WorkspaceLLMSelection";
 
 export default function ChatSettings({ workspace }) {
   const [settings, setSettings] = useState({});
@@ -44,35 +44,45 @@ export default function ChatSettings({ workspace }) {
 
   if (!workspace) return null;
   return (
-    <form
-      ref={formEl}
-      onSubmit={handleUpdate}
-      className="w-1/2 flex flex-col gap-y-6"
-    >
-      <ChatModeSelection workspace={workspace} setHasChanges={setHasChanges} />
-      <ChatModelSelection
-        settings={settings}
-        workspace={workspace}
-        setHasChanges={setHasChanges}
-      />
-      <ChatHistorySettings
-        workspace={workspace}
-        setHasChanges={setHasChanges}
-      />
-      <ChatPromptSettings workspace={workspace} setHasChanges={setHasChanges} />
-      <ChatTemperatureSettings
-        settings={settings}
-        workspace={workspace}
-        setHasChanges={setHasChanges}
-      />
-      {hasChanges && (
-        <button
-          type="submit"
-          className="w-fit transition-all duration-300 border border-slate-200 px-5 py-2.5 rounded-lg text-white text-sm items-center flex gap-x-2 hover:bg-slate-200 hover:text-slate-800 focus:ring-gray-800"
-        >
-          {saving ? "Updating..." : "Update workspace"}
-        </button>
-      )}
-    </form>
+    <div id="workspace-chat-settings-container">
+      <form
+        ref={formEl}
+        onSubmit={handleUpdate}
+        id="chat-settings-form"
+        className="w-1/2 flex flex-col gap-y-6"
+      >
+        <WorkspaceLLMSelection
+          settings={settings}
+          workspace={workspace}
+          setHasChanges={setHasChanges}
+        />
+        <ChatModeSelection
+          workspace={workspace}
+          setHasChanges={setHasChanges}
+        />
+        <ChatHistorySettings
+          workspace={workspace}
+          setHasChanges={setHasChanges}
+        />
+        <ChatPromptSettings
+          workspace={workspace}
+          setHasChanges={setHasChanges}
+        />
+        <ChatTemperatureSettings
+          settings={settings}
+          workspace={workspace}
+          setHasChanges={setHasChanges}
+        />
+        {hasChanges && (
+          <button
+            type="submit"
+            form="chat-settings-form"
+            className="w-fit transition-all duration-300 border border-slate-200 px-5 py-2.5 rounded-lg text-white text-sm items-center flex gap-x-2 hover:bg-slate-200 hover:text-slate-800 focus:ring-gray-800"
+          >
+            {saving ? "Updating..." : "Update workspace"}
+          </button>
+        )}
+      </form>
+    </div>
   );
 }
diff --git a/server/endpoints/workspaces.js b/server/endpoints/workspaces.js
index da9e2ad941261480b1c071cd4159444bfde6dca6..1c87dc366965a0dfe20b7afdf0e1edc67a7858b4 100644
--- a/server/endpoints/workspaces.js
+++ b/server/endpoints/workspaces.js
@@ -508,7 +508,7 @@ function workspaceEndpoints(app) {
           if (fs.existsSync(oldPfpPath)) fs.unlinkSync(oldPfpPath);
         }
 
-        const { workspace, message } = await Workspace.update(
+        const { workspace, message } = await Workspace._update(
           workspaceRecord.id,
           {
             pfpFilename: uploadedFileName,
@@ -547,7 +547,7 @@ function workspaceEndpoints(app) {
           if (fs.existsSync(oldPfpPath)) fs.unlinkSync(oldPfpPath);
         }
 
-        const { workspace, message } = await Workspace.update(
+        const { workspace, message } = await Workspace._update(
           workspaceRecord.id,
           {
             pfpFilename: null,
diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js
index c4529ad914725cbd1ad743822ff13f749ca9f2c2..080a01f08727982edc698badfff06f01d0650a23 100644
--- a/server/models/systemSettings.js
+++ b/server/models/systemSettings.js
@@ -57,103 +57,13 @@ const SystemSettings = {
       // VectorDB Provider Selection Settings & Configs
       // --------------------------------------------------------
       VectorDB: vectorDB,
-      // Pinecone DB Keys
-      PineConeKey: !!process.env.PINECONE_API_KEY,
-      PineConeIndex: process.env.PINECONE_INDEX,
-
-      // Chroma DB Keys
-      ChromaEndpoint: process.env.CHROMA_ENDPOINT,
-      ChromaApiHeader: process.env.CHROMA_API_HEADER,
-      ChromaApiKey: !!process.env.CHROMA_API_KEY,
-
-      // Weaviate DB Keys
-      WeaviateEndpoint: process.env.WEAVIATE_ENDPOINT,
-      WeaviateApiKey: process.env.WEAVIATE_API_KEY,
-
-      // QDrant DB Keys
-      QdrantEndpoint: process.env.QDRANT_ENDPOINT,
-      QdrantApiKey: process.env.QDRANT_API_KEY,
-
-      // Milvus DB Keys
-      MilvusAddress: process.env.MILVUS_ADDRESS,
-      MilvusUsername: process.env.MILVUS_USERNAME,
-      MilvusPassword: !!process.env.MILVUS_PASSWORD,
-
-      // Zilliz DB Keys
-      ZillizEndpoint: process.env.ZILLIZ_ENDPOINT,
-      ZillizApiToken: process.env.ZILLIZ_API_TOKEN,
-
-      // AstraDB Keys
-      AstraDBApplicationToken: process?.env?.ASTRA_DB_APPLICATION_TOKEN,
-      AstraDBEndpoint: process?.env?.ASTRA_DB_ENDPOINT,
+      ...this.vectorDBPreferenceKeys(),
 
       // --------------------------------------------------------
       // LLM Provider Selection Settings & Configs
       // --------------------------------------------------------
       LLMProvider: llmProvider,
-      // OpenAI Keys
-      OpenAiKey: !!process.env.OPEN_AI_KEY,
-      OpenAiModelPref: process.env.OPEN_MODEL_PREF || "gpt-3.5-turbo",
-
-      // Azure + OpenAI Keys
-      AzureOpenAiEndpoint: process.env.AZURE_OPENAI_ENDPOINT,
-      AzureOpenAiKey: !!process.env.AZURE_OPENAI_KEY,
-      AzureOpenAiModelPref: process.env.OPEN_MODEL_PREF,
-      AzureOpenAiEmbeddingModelPref: process.env.EMBEDDING_MODEL_PREF,
-      AzureOpenAiTokenLimit: process.env.AZURE_OPENAI_TOKEN_LIMIT || 4096,
-
-      // Anthropic Keys
-      AnthropicApiKey: !!process.env.ANTHROPIC_API_KEY,
-      AnthropicModelPref: process.env.ANTHROPIC_MODEL_PREF || "claude-2",
-
-      // Gemini Keys
-      GeminiLLMApiKey: !!process.env.GEMINI_API_KEY,
-      GeminiLLMModelPref: process.env.GEMINI_LLM_MODEL_PREF || "gemini-pro",
-
-      // LMStudio Keys
-      LMStudioBasePath: process.env.LMSTUDIO_BASE_PATH,
-      LMStudioTokenLimit: process.env.LMSTUDIO_MODEL_TOKEN_LIMIT,
-      LMStudioModelPref: process.env.LMSTUDIO_MODEL_PREF,
-
-      // LocalAI Keys
-      LocalAiApiKey: !!process.env.LOCAL_AI_API_KEY,
-      LocalAiBasePath: process.env.LOCAL_AI_BASE_PATH,
-      LocalAiModelPref: process.env.LOCAL_AI_MODEL_PREF,
-      LocalAiTokenLimit: process.env.LOCAL_AI_MODEL_TOKEN_LIMIT,
-
-      // Ollama LLM Keys
-      OllamaLLMBasePath: process.env.OLLAMA_BASE_PATH,
-      OllamaLLMModelPref: process.env.OLLAMA_MODEL_PREF,
-      OllamaLLMTokenLimit: process.env.OLLAMA_MODEL_TOKEN_LIMIT,
-
-      // TogetherAI Keys
-      TogetherAiApiKey: !!process.env.TOGETHER_AI_API_KEY,
-      TogetherAiModelPref: process.env.TOGETHER_AI_MODEL_PREF,
-
-      // Perplexity AI Keys
-      PerplexityApiKey: !!process.env.PERPLEXITY_API_KEY,
-      PerplexityModelPref: process.env.PERPLEXITY_MODEL_PREF,
-
-      // OpenRouter Keys
-      OpenRouterApiKey: !!process.env.OPENROUTER_API_KEY,
-      OpenRouterModelPref: process.env.OPENROUTER_MODEL_PREF,
-
-      // Mistral AI (API) Keys
-      MistralApiKey: !!process.env.MISTRAL_API_KEY,
-      MistralModelPref: process.env.MISTRAL_MODEL_PREF,
-
-      // Groq AI API Keys
-      GroqApiKey: !!process.env.GROQ_API_KEY,
-      GroqModelPref: process.env.GROQ_MODEL_PREF,
-
-      // Native LLM Keys
-      NativeLLMModelPref: process.env.NATIVE_LLM_MODEL_PREF,
-      NativeLLMTokenLimit: process.env.NATIVE_LLM_MODEL_TOKEN_LIMIT,
-
-      // HuggingFace Dedicated Inference
-      HuggingFaceLLMEndpoint: process.env.HUGGING_FACE_LLM_ENDPOINT,
-      HuggingFaceLLMAccessToken: !!process.env.HUGGING_FACE_LLM_API_KEY,
-      HuggingFaceLLMTokenLimit: process.env.HUGGING_FACE_LLM_TOKEN_LIMIT,
+      ...this.llmPreferenceKeys(),
 
       // --------------------------------------------------------
       // Whisper (Audio transcription) Selection Settings & Configs
@@ -273,6 +183,108 @@ const SystemSettings = {
       return false;
     }
   },
+
+  vectorDBPreferenceKeys: function () {
+    return {
+      // Pinecone DB Keys
+      PineConeKey: !!process.env.PINECONE_API_KEY,
+      PineConeIndex: process.env.PINECONE_INDEX,
+
+      // Chroma DB Keys
+      ChromaEndpoint: process.env.CHROMA_ENDPOINT,
+      ChromaApiHeader: process.env.CHROMA_API_HEADER,
+      ChromaApiKey: !!process.env.CHROMA_API_KEY,
+
+      // Weaviate DB Keys
+      WeaviateEndpoint: process.env.WEAVIATE_ENDPOINT,
+      WeaviateApiKey: process.env.WEAVIATE_API_KEY,
+
+      // QDrant DB Keys
+      QdrantEndpoint: process.env.QDRANT_ENDPOINT,
+      QdrantApiKey: process.env.QDRANT_API_KEY,
+
+      // Milvus DB Keys
+      MilvusAddress: process.env.MILVUS_ADDRESS,
+      MilvusUsername: process.env.MILVUS_USERNAME,
+      MilvusPassword: !!process.env.MILVUS_PASSWORD,
+
+      // Zilliz DB Keys
+      ZillizEndpoint: process.env.ZILLIZ_ENDPOINT,
+      ZillizApiToken: process.env.ZILLIZ_API_TOKEN,
+
+      // AstraDB Keys
+      AstraDBApplicationToken: process?.env?.ASTRA_DB_APPLICATION_TOKEN,
+      AstraDBEndpoint: process?.env?.ASTRA_DB_ENDPOINT,
+    };
+  },
+
+  llmPreferenceKeys: function () {
+    return {
+      // OpenAI Keys
+      OpenAiKey: !!process.env.OPEN_AI_KEY,
+      OpenAiModelPref: process.env.OPEN_MODEL_PREF || "gpt-3.5-turbo",
+
+      // Azure + OpenAI Keys
+      AzureOpenAiEndpoint: process.env.AZURE_OPENAI_ENDPOINT,
+      AzureOpenAiKey: !!process.env.AZURE_OPENAI_KEY,
+      AzureOpenAiModelPref: process.env.OPEN_MODEL_PREF,
+      AzureOpenAiEmbeddingModelPref: process.env.EMBEDDING_MODEL_PREF,
+      AzureOpenAiTokenLimit: process.env.AZURE_OPENAI_TOKEN_LIMIT || 4096,
+
+      // Anthropic Keys
+      AnthropicApiKey: !!process.env.ANTHROPIC_API_KEY,
+      AnthropicModelPref: process.env.ANTHROPIC_MODEL_PREF || "claude-2",
+
+      // Gemini Keys
+      GeminiLLMApiKey: !!process.env.GEMINI_API_KEY,
+      GeminiLLMModelPref: process.env.GEMINI_LLM_MODEL_PREF || "gemini-pro",
+
+      // LMStudio Keys
+      LMStudioBasePath: process.env.LMSTUDIO_BASE_PATH,
+      LMStudioTokenLimit: process.env.LMSTUDIO_MODEL_TOKEN_LIMIT,
+      LMStudioModelPref: process.env.LMSTUDIO_MODEL_PREF,
+
+      // LocalAI Keys
+      LocalAiApiKey: !!process.env.LOCAL_AI_API_KEY,
+      LocalAiBasePath: process.env.LOCAL_AI_BASE_PATH,
+      LocalAiModelPref: process.env.LOCAL_AI_MODEL_PREF,
+      LocalAiTokenLimit: process.env.LOCAL_AI_MODEL_TOKEN_LIMIT,
+
+      // Ollama LLM Keys
+      OllamaLLMBasePath: process.env.OLLAMA_BASE_PATH,
+      OllamaLLMModelPref: process.env.OLLAMA_MODEL_PREF,
+      OllamaLLMTokenLimit: process.env.OLLAMA_MODEL_TOKEN_LIMIT,
+
+      // TogetherAI Keys
+      TogetherAiApiKey: !!process.env.TOGETHER_AI_API_KEY,
+      TogetherAiModelPref: process.env.TOGETHER_AI_MODEL_PREF,
+
+      // Perplexity AI Keys
+      PerplexityApiKey: !!process.env.PERPLEXITY_API_KEY,
+      PerplexityModelPref: process.env.PERPLEXITY_MODEL_PREF,
+
+      // OpenRouter Keys
+      OpenRouterApiKey: !!process.env.OPENROUTER_API_KEY,
+      OpenRouterModelPref: process.env.OPENROUTER_MODEL_PREF,
+
+      // Mistral AI (API) Keys
+      MistralApiKey: !!process.env.MISTRAL_API_KEY,
+      MistralModelPref: process.env.MISTRAL_MODEL_PREF,
+
+      // Groq AI API Keys
+      GroqApiKey: !!process.env.GROQ_API_KEY,
+      GroqModelPref: process.env.GROQ_MODEL_PREF,
+
+      // Native LLM Keys
+      NativeLLMModelPref: process.env.NATIVE_LLM_MODEL_PREF,
+      NativeLLMTokenLimit: process.env.NATIVE_LLM_MODEL_TOKEN_LIMIT,
+
+      // HuggingFace Dedicated Inference
+      HuggingFaceLLMEndpoint: process.env.HUGGING_FACE_LLM_ENDPOINT,
+      HuggingFaceLLMAccessToken: !!process.env.HUGGING_FACE_LLM_API_KEY,
+      HuggingFaceLLMTokenLimit: process.env.HUGGING_FACE_LLM_TOKEN_LIMIT,
+    };
+  },
 };
 
 module.exports.SystemSettings = SystemSettings;
diff --git a/server/models/workspace.js b/server/models/workspace.js
index f061ca206f023aee97d2a1c384b84454eb939b96..b905c199ca8dc89fd5bfc124a173c93998c444c9 100644
--- a/server/models/workspace.js
+++ b/server/models/workspace.js
@@ -19,6 +19,7 @@ const Workspace = {
     "lastUpdatedAt",
     "openAiPrompt",
     "similarityThreshold",
+    "chatProvider",
     "chatModel",
     "topN",
     "chatMode",
@@ -52,19 +53,42 @@ const Workspace = {
     }
   },
 
-  update: async function (id = null, data = {}) {
+  update: async function (id = null, updates = {}) {
     if (!id) throw new Error("No workspace id provided for update");
 
-    const validKeys = Object.keys(data).filter((key) =>
+    const validFields = Object.keys(updates).filter((key) =>
       this.writable.includes(key)
     );
-    if (validKeys.length === 0)
+
+    Object.entries(updates).forEach(([key]) => {
+      if (validFields.includes(key)) return;
+      delete updates[key];
+    });
+
+    if (Object.keys(updates).length === 0)
       return { workspace: { id }, message: "No valid fields to update!" };
 
+    // If the user unset the chatProvider we will need
+    // to then clear the chatModel as well to prevent confusion during
+    // LLM loading.
+    if (updates?.chatProvider === "default") {
+      updates.chatProvider = null;
+      updates.chatModel = null;
+    }
+
+    return this._update(id, updates);
+  },
+
+  // Explicit update of settings + key validations.
+  // Only use this method when directly setting a key value
+  // that takes no user input for the keys being modified.
+  _update: async function (id = null, data = {}) {
+    if (!id) throw new Error("No workspace id provided for update");
+
     try {
       const workspace = await prisma.workspaces.update({
         where: { id },
-        data, // TODO: strict validation on writables here.
+        data,
       });
       return { workspace, message: null };
     } catch (error) {
@@ -229,47 +253,40 @@ const Workspace = {
     }
   },
 
-  resetWorkspaceChatModels: async () => {
-    try {
-      await prisma.workspaces.updateMany({
-        data: {
-          chatModel: null,
-        },
-      });
-      return { success: true, error: null };
-    } catch (error) {
-      console.error("Error resetting workspace chat models:", error.message);
-      return { success: false, error: error.message };
-    }
-  },
-
   trackChange: async function (prevData, newData, user) {
     try {
-      const { Telemetry } = require("./telemetry");
-      const { EventLogs } = require("./eventLogs");
-      if (
-        !newData?.openAiPrompt ||
-        newData?.openAiPrompt === this.defaultPrompt ||
-        newData?.openAiPrompt === prevData?.openAiPrompt
-      )
-        return;
-
-      await Telemetry.sendTelemetry("workspace_prompt_changed");
-      await EventLogs.logEvent(
-        "workspace_prompt_changed",
-        {
-          workspaceName: prevData?.name,
-          prevSystemPrompt: prevData?.openAiPrompt || this.defaultPrompt,
-          newSystemPrompt: newData?.openAiPrompt,
-        },
-        user?.id
-      );
+      await this._trackWorkspacePromptChange(prevData, newData, user);
       return;
     } catch (error) {
       console.error("Error tracking workspace change:", error.message);
       return;
     }
   },
+
+  // We are only tracking this change to determine the need to a prompt library or
+  // prompt assistant feature. If this is something you would like to see - tell us on GitHub!
+  _trackWorkspacePromptChange: async function (prevData, newData, user) {
+    const { Telemetry } = require("./telemetry");
+    const { EventLogs } = require("./eventLogs");
+    if (
+      !newData?.openAiPrompt ||
+      newData?.openAiPrompt === this.defaultPrompt ||
+      newData?.openAiPrompt === prevData?.openAiPrompt
+    )
+      return;
+
+    await Telemetry.sendTelemetry("workspace_prompt_changed");
+    await EventLogs.logEvent(
+      "workspace_prompt_changed",
+      {
+        workspaceName: prevData?.name,
+        prevSystemPrompt: prevData?.openAiPrompt || this.defaultPrompt,
+        newSystemPrompt: newData?.openAiPrompt,
+      },
+      user?.id
+    );
+    return;
+  },
 };
 
 module.exports = { Workspace };
diff --git a/server/prisma/migrations/20240405015034_init/migration.sql b/server/prisma/migrations/20240405015034_init/migration.sql
new file mode 100644
index 0000000000000000000000000000000000000000..54a39d940a105816b68fa55b915b154978848e49
--- /dev/null
+++ b/server/prisma/migrations/20240405015034_init/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "workspaces" ADD COLUMN "chatProvider" TEXT;
diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma
index fbb5f61d4c1fa51ba7a8cc18a749ab095ce04ca9..1e589b0f1f94e163288bf94c8a8195165e3b850e 100644
--- a/server/prisma/schema.prisma
+++ b/server/prisma/schema.prisma
@@ -98,6 +98,7 @@ model workspaces {
   lastUpdatedAt                DateTime                       @default(now())
   openAiPrompt                 String?
   similarityThreshold          Float?                         @default(0.25)
+  chatProvider                 String?
   chatModel                    String?
   topN                         Int?                           @default(4)
   chatMode                     String?                        @default("chat")
diff --git a/server/utils/chats/embed.js b/server/utils/chats/embed.js
index f748a3a5d3038308cb218103ed46c4da5fe529a6..497b2c8e44930bba9435e177691b06db89452824 100644
--- a/server/utils/chats/embed.js
+++ b/server/utils/chats/embed.js
@@ -28,7 +28,9 @@ async function streamChatWithForEmbed(
     embed.workspace.openAiTemp = parseFloat(temperatureOverride);
 
   const uuid = uuidv4();
-  const LLMConnector = getLLMProvider(chatModel ?? embed.workspace?.chatModel);
+  const LLMConnector = getLLMProvider({
+    model: chatModel ?? embed.workspace?.chatModel,
+  });
   const VectorDb = getVectorDbClass();
   const { safe, reasons = [] } = await LLMConnector.isSafe(message);
   if (!safe) {
diff --git a/server/utils/chats/index.js b/server/utils/chats/index.js
index 10df9983f071cd357f16a79723d6bc8ed3901355..7e40b9a8bed03669007e96332dc8d8a91d6fd902 100644
--- a/server/utils/chats/index.js
+++ b/server/utils/chats/index.js
@@ -37,7 +37,10 @@ async function chatWithWorkspace(
     return await VALID_COMMANDS[command](workspace, message, uuid, user);
   }
 
-  const LLMConnector = getLLMProvider(workspace?.chatModel);
+  const LLMConnector = getLLMProvider({
+    provider: workspace?.chatProvider,
+    model: workspace?.chatModel,
+  });
   const VectorDb = getVectorDbClass();
   const { safe, reasons = [] } = await LLMConnector.isSafe(message);
   if (!safe) {
diff --git a/server/utils/chats/stream.js b/server/utils/chats/stream.js
index f1a335bc8ea2161ee91409cc39884def3d30c7eb..0ec969eba4254afda2ce069cbdcf99bcd9facc7f 100644
--- a/server/utils/chats/stream.js
+++ b/server/utils/chats/stream.js
@@ -35,7 +35,10 @@ async function streamChatWithWorkspace(
     return;
   }
 
-  const LLMConnector = getLLMProvider(workspace?.chatModel);
+  const LLMConnector = getLLMProvider({
+    provider: workspace?.chatProvider,
+    model: workspace?.chatModel,
+  });
   const VectorDb = getVectorDbClass();
   const { safe, reasons = [] } = await LLMConnector.isSafe(message);
   if (!safe) {
diff --git a/server/utils/helpers/index.js b/server/utils/helpers/index.js
index 7836097256ce75b3a70b931513b0b76d7c49cd34..a441bf82f51c52ecb727fc91f1ee1cfa19a3acfd 100644
--- a/server/utils/helpers/index.js
+++ b/server/utils/helpers/index.js
@@ -30,52 +30,53 @@ function getVectorDbClass() {
   }
 }
 
-function getLLMProvider(modelPreference = null) {
-  const vectorSelection = process.env.LLM_PROVIDER || "openai";
+function getLLMProvider({ provider = null, model = null } = {}) {
+  const LLMSelection = provider ?? process.env.LLM_PROVIDER ?? "openai";
   const embedder = getEmbeddingEngineSelection();
-  switch (vectorSelection) {
+
+  switch (LLMSelection) {
     case "openai":
       const { OpenAiLLM } = require("../AiProviders/openAi");
-      return new OpenAiLLM(embedder, modelPreference);
+      return new OpenAiLLM(embedder, model);
     case "azure":
       const { AzureOpenAiLLM } = require("../AiProviders/azureOpenAi");
-      return new AzureOpenAiLLM(embedder, modelPreference);
+      return new AzureOpenAiLLM(embedder, model);
     case "anthropic":
       const { AnthropicLLM } = require("../AiProviders/anthropic");
-      return new AnthropicLLM(embedder, modelPreference);
+      return new AnthropicLLM(embedder, model);
     case "gemini":
       const { GeminiLLM } = require("../AiProviders/gemini");
-      return new GeminiLLM(embedder, modelPreference);
+      return new GeminiLLM(embedder, model);
     case "lmstudio":
       const { LMStudioLLM } = require("../AiProviders/lmStudio");
-      return new LMStudioLLM(embedder, modelPreference);
+      return new LMStudioLLM(embedder, model);
     case "localai":
       const { LocalAiLLM } = require("../AiProviders/localAi");
-      return new LocalAiLLM(embedder, modelPreference);
+      return new LocalAiLLM(embedder, model);
     case "ollama":
       const { OllamaAILLM } = require("../AiProviders/ollama");
-      return new OllamaAILLM(embedder, modelPreference);
+      return new OllamaAILLM(embedder, model);
     case "togetherai":
       const { TogetherAiLLM } = require("../AiProviders/togetherAi");
-      return new TogetherAiLLM(embedder, modelPreference);
+      return new TogetherAiLLM(embedder, model);
     case "perplexity":
       const { PerplexityLLM } = require("../AiProviders/perplexity");
-      return new PerplexityLLM(embedder, modelPreference);
+      return new PerplexityLLM(embedder, model);
     case "openrouter":
       const { OpenRouterLLM } = require("../AiProviders/openRouter");
-      return new OpenRouterLLM(embedder, modelPreference);
+      return new OpenRouterLLM(embedder, model);
     case "mistral":
       const { MistralLLM } = require("../AiProviders/mistral");
-      return new MistralLLM(embedder, modelPreference);
+      return new MistralLLM(embedder, model);
     case "native":
       const { NativeLLM } = require("../AiProviders/native");
-      return new NativeLLM(embedder, modelPreference);
+      return new NativeLLM(embedder, model);
     case "huggingface":
       const { HuggingFaceLLM } = require("../AiProviders/huggingface");
-      return new HuggingFaceLLM(embedder, modelPreference);
+      return new HuggingFaceLLM(embedder, model);
     case "groq":
       const { GroqLLM } = require("../AiProviders/groq");
-      return new GroqLLM(embedder, modelPreference);
+      return new GroqLLM(embedder, model);
     default:
       throw new Error("ENV: No LLM_PROVIDER value found in environment!");
   }
diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js
index 12c45af2686a534b6b0bcb48919a49209e139619..a026fe33804fdad23e45cab7558e0b35d0066417 100644
--- a/server/utils/helpers/updateENV.js
+++ b/server/utils/helpers/updateENV.js
@@ -2,7 +2,6 @@ const KEY_MAPPING = {
   LLMProvider: {
     envKey: "LLM_PROVIDER",
     checks: [isNotEmpty, supportedLLM],
-    postUpdate: [wipeWorkspaceModelPreference],
   },
   // OpenAI Settings
   OpenAiKey: {
@@ -493,15 +492,6 @@ function validHuggingFaceEndpoint(input = "") {
     : null;
 }
 
-// If the LLMProvider has changed we need to reset all workspace model preferences to
-// null since the provider<>model name combination will be invalid for whatever the new
-// provider is.
-async function wipeWorkspaceModelPreference(key, prev, next) {
-  if (prev === next) return;
-  const { Workspace } = require("../../models/workspace");
-  await Workspace.resetWorkspaceChatModels();
-}
-
 // 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