diff --git a/.github/ISSUE_TEMPLATE/01_bug.yml b/.github/ISSUE_TEMPLATE/01_bug.yml
index d59f0e521..3b97773e9 100644
--- a/.github/ISSUE_TEMPLATE/01_bug.yml
+++ b/.github/ISSUE_TEMPLATE/01_bug.yml
@@ -17,6 +17,7 @@ body:
- Docker (remote machine)
- Local development
- AnythingLLM desktop app
+ - All versions
- Not listed
default: 0
validations:
diff --git a/README.md b/README.md
index 88a4f489a..842efa071 100644
--- a/README.md
+++ b/README.md
@@ -5,8 +5,8 @@
- AnythingLLM: A private ChatGPT to chat with anything! .
- An efficient, customizable, and open-source enterprise-ready document chatbot solution.
+ AnythingLLM: The all-in-one AI app you were looking for.
+ Chat with your docs, use AI Agents, hyper-configurable, multi-user, & no fustrating set up required.
@@ -25,7 +25,7 @@
-👉 AnythingLLM for desktop is in public beta ! Download Now
+👉 AnythingLLM for desktop (Mac, Windows, & Linux)! Download Now
A full-stack application that enables you to turn any document, resource, or piece of content into context that any LLM can use as references during chatting. This application allows you to pick and choose which LLM or Vector Database you want to use as well as supporting multi-user management and permissions.
@@ -48,7 +48,8 @@ AnythingLLM divides your documents into objects called `workspaces`. A Workspace
Some cool features of AnythingLLM
- **Multi-user instance support and permissioning**
-- **_New_** [Custom Embeddable Chat widget for your website](./embed/README.md)
+- Agents inside your workspace (browse the web, run code, etc)
+- [Custom Embeddable Chat widget for your website](./embed/README.md)
- Multiple document type support (PDF, TXT, DOCX, etc)
- Manage documents in your vector database from a simple UI
- Two chat modes `conversation` and `query`. Conversation retains previous questions and amendments. Query is simple QA against your documents
@@ -82,9 +83,9 @@ Some cool features of AnythingLLM
- [AnythingLLM Native Embedder](/server/storage/models/README.md) (default)
- [OpenAI](https://openai.com)
- [Azure OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service)
-- [LM Studio (all)](https://lmstudio.ai)
- [LocalAi (all)](https://localai.io/)
- [Ollama (all)](https://ollama.ai/)
+- [LM Studio (all)](https://lmstudio.ai)
**Supported Transcription models:**
diff --git a/collector/processSingleFile/convert/asPDF.js b/collector/processSingleFile/convert/asPDF.js
index e81fe6c76..458277754 100644
--- a/collector/processSingleFile/convert/asPDF.js
+++ b/collector/processSingleFile/convert/asPDF.js
@@ -22,7 +22,7 @@ async function asPDF({ fullFilePath = "", filename = "" }) {
doc.metadata?.loc?.pageNumber || "unknown"
} --`
);
- if (!doc.pageContent.length) continue;
+ if (!doc.pageContent || !doc.pageContent.length) continue;
pageContent.push(doc.pageContent);
}
diff --git a/docker/.env.example b/docker/.env.example
index 32f2a55d4..aabc139f8 100644
--- a/docker/.env.example
+++ b/docker/.env.example
@@ -85,10 +85,15 @@ GID='1000'
# EMBEDDING_MODEL_MAX_CHUNK_LENGTH=1000 # The max chunk size in chars a string to embed can be
# EMBEDDING_ENGINE='ollama'
-# EMBEDDING_BASE_PATH='http://127.0.0.1:11434'
+# EMBEDDING_BASE_PATH='http://host.docker.internal:11434'
# EMBEDDING_MODEL_PREF='nomic-embed-text:latest'
# EMBEDDING_MODEL_MAX_CHUNK_LENGTH=8192
+# EMBEDDING_ENGINE='lmstudio'
+# EMBEDDING_BASE_PATH='https://host.docker.internal:1234/v1'
+# EMBEDDING_MODEL_PREF='nomic-ai/nomic-embed-text-v1.5-GGUF/nomic-embed-text-v1.5.Q4_0.gguf'
+# EMBEDDING_MODEL_MAX_CHUNK_LENGTH=8192
+
###########################################
######## Vector Database Selection ########
###########################################
diff --git a/frontend/src/components/EmbeddingSelection/LMStudioOptions/index.jsx b/frontend/src/components/EmbeddingSelection/LMStudioOptions/index.jsx
new file mode 100644
index 000000000..1192ce675
--- /dev/null
+++ b/frontend/src/components/EmbeddingSelection/LMStudioOptions/index.jsx
@@ -0,0 +1,120 @@
+import React, { useEffect, useState } from "react";
+import System from "@/models/system";
+
+export default function LMStudioEmbeddingOptions({ settings }) {
+ const [basePathValue, setBasePathValue] = useState(
+ settings?.EmbeddingBasePath
+ );
+ const [basePath, setBasePath] = useState(settings?.EmbeddingBasePath);
+
+ return (
+
+
+
+
+ LMStudio Base URL
+
+ setBasePathValue(e.target.value)}
+ onBlur={() => setBasePath(basePathValue)}
+ required={true}
+ autoComplete="off"
+ spellCheck={false}
+ />
+
+
+
+
+ Max embedding chunk length
+
+ e.target.blur()}
+ defaultValue={settings?.EmbeddingModelMaxChunkLength}
+ required={false}
+ autoComplete="off"
+ />
+
+
+
+ );
+}
+
+function LMStudioModelSelection({ settings, basePath = null }) {
+ const [customModels, setCustomModels] = useState([]);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ async function findCustomModels() {
+ if (!basePath || !basePath.includes("/v1")) {
+ setCustomModels([]);
+ setLoading(false);
+ return;
+ }
+ setLoading(true);
+ const { models } = await System.customModels("lmstudio", null, basePath);
+ setCustomModels(models || []);
+ setLoading(false);
+ }
+ findCustomModels();
+ }, [basePath]);
+
+ if (loading || customModels.length == 0) {
+ return (
+
+
+ Chat Model Selection
+
+
+
+ {basePath?.includes("/v1")
+ ? "-- loading available models --"
+ : "-- waiting for URL --"}
+
+
+
+ );
+ }
+
+ return (
+
+
+ Chat Model Selection
+
+
+ {customModels.length > 0 && (
+
+ {customModels.map((model) => {
+ return (
+
+ {model.id}
+
+ );
+ })}
+
+ )}
+
+
+ );
+}
diff --git a/frontend/src/components/LLMSelection/GeminiLLMOptions/index.jsx b/frontend/src/components/LLMSelection/GeminiLLMOptions/index.jsx
index a46e51329..8cb513f31 100644
--- a/frontend/src/components/LLMSelection/GeminiLLMOptions/index.jsx
+++ b/frontend/src/components/LLMSelection/GeminiLLMOptions/index.jsx
@@ -29,7 +29,7 @@ export default function GeminiLLMOptions({ settings }) {
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) => {
+ {["gemini-pro", "gemini-1.5-pro-latest"].map((model) => {
return (
{model}
diff --git a/frontend/src/hooks/useGetProvidersModels.js b/frontend/src/hooks/useGetProvidersModels.js
index 5dc5cd2ed..b6cb403e1 100644
--- a/frontend/src/hooks/useGetProvidersModels.js
+++ b/frontend/src/hooks/useGetProvidersModels.js
@@ -5,7 +5,7 @@ import { useEffect, useState } from "react";
export const DISABLED_PROVIDERS = ["azure", "lmstudio", "native"];
const PROVIDER_DEFAULT_MODELS = {
openai: [],
- gemini: ["gemini-pro"],
+ gemini: ["gemini-pro", "gemini-1.5-pro-latest"],
anthropic: [
"claude-instant-1.2",
"claude-2.0",
diff --git a/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx b/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx
index ad7c08d35..25dcd62d3 100644
--- a/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx
+++ b/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx
@@ -8,6 +8,7 @@ import OpenAiLogo from "@/media/llmprovider/openai.png";
import AzureOpenAiLogo from "@/media/llmprovider/azure.png";
import LocalAiLogo from "@/media/llmprovider/localai.png";
import OllamaLogo from "@/media/llmprovider/ollama.png";
+import LMStudioLogo from "@/media/llmprovider/lmstudio.png";
import PreLoader from "@/components/Preloader";
import ChangeWarningModal from "@/components/ChangeWarning";
import OpenAiOptions from "@/components/EmbeddingSelection/OpenAiOptions";
@@ -15,16 +16,65 @@ import AzureAiOptions from "@/components/EmbeddingSelection/AzureAiOptions";
import LocalAiOptions from "@/components/EmbeddingSelection/LocalAiOptions";
import NativeEmbeddingOptions from "@/components/EmbeddingSelection/NativeEmbeddingOptions";
import OllamaEmbeddingOptions from "@/components/EmbeddingSelection/OllamaOptions";
+import LMStudioEmbeddingOptions from "@/components/EmbeddingSelection/LMStudioOptions";
import EmbedderItem from "@/components/EmbeddingSelection/EmbedderItem";
import { CaretUpDown, MagnifyingGlass, X } from "@phosphor-icons/react";
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.",
+ },
+ {
+ name: "LM Studio",
+ value: "lmstudio",
+ logo: LMStudioLogo,
+ options: (settings) => ,
+ description:
+ "Discover, download, and run thousands of cutting edge LLMs in a few clicks.",
+ },
+];
+
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 +84,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 +151,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 +306,7 @@ export default function GeneralEmbeddingPreference() {
{selectedEmbedder &&
EMBEDDERS.find(
(embedder) => embedder.value === selectedEmbedder
- )?.options}
+ )?.options(settings)}
@@ -290,7 +314,7 @@ export default function GeneralEmbeddingPreference() {
)}
diff --git a/frontend/src/pages/OnboardingFlow/Steps/DataHandling/index.jsx b/frontend/src/pages/OnboardingFlow/Steps/DataHandling/index.jsx
index bd8487842..11612b99b 100644
--- a/frontend/src/pages/OnboardingFlow/Steps/DataHandling/index.jsx
+++ b/frontend/src/pages/OnboardingFlow/Steps/DataHandling/index.jsx
@@ -237,6 +237,13 @@ export const EMBEDDING_ENGINE_PRIVACY = {
],
logo: OllamaLogo,
},
+ lmstudio: {
+ name: "LMStudio",
+ description: [
+ "Your document text is embedded privately on the server running LMStudio",
+ ],
+ logo: LMStudioLogo,
+ },
};
export default function DataHandling({ setHeader, setForwardBtn, setBackBtn }) {
diff --git a/frontend/src/pages/OnboardingFlow/Steps/EmbeddingPreference/index.jsx b/frontend/src/pages/OnboardingFlow/Steps/EmbeddingPreference/index.jsx
index 1932309e4..fc44a68de 100644
--- a/frontend/src/pages/OnboardingFlow/Steps/EmbeddingPreference/index.jsx
+++ b/frontend/src/pages/OnboardingFlow/Steps/EmbeddingPreference/index.jsx
@@ -5,11 +5,13 @@ import OpenAiLogo from "@/media/llmprovider/openai.png";
import AzureOpenAiLogo from "@/media/llmprovider/azure.png";
import LocalAiLogo from "@/media/llmprovider/localai.png";
import OllamaLogo from "@/media/llmprovider/ollama.png";
+import LMStudioLogo from "@/media/llmprovider/lmstudio.png";
import NativeEmbeddingOptions from "@/components/EmbeddingSelection/NativeEmbeddingOptions";
import OpenAiOptions from "@/components/EmbeddingSelection/OpenAiOptions";
import AzureAiOptions from "@/components/EmbeddingSelection/AzureAiOptions";
import LocalAiOptions from "@/components/EmbeddingSelection/LocalAiOptions";
import OllamaEmbeddingOptions from "@/components/EmbeddingSelection/OllamaOptions";
+import LMStudioEmbeddingOptions from "@/components/EmbeddingSelection/LMStudioOptions";
import EmbedderItem from "@/components/EmbeddingSelection/EmbedderItem";
import System from "@/models/system";
import paths from "@/utils/paths";
@@ -19,6 +21,52 @@ import { useNavigate } from "react-router-dom";
const TITLE = "Embedding Preference";
const DESCRIPTION =
"AnythingLLM can work with many embedding models. This will be the model which turns documents into vectors.";
+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.",
+ },
+ {
+ name: "LM Studio",
+ value: "lmstudio",
+ logo: LMStudioLogo,
+ options: (settings) => ,
+ description:
+ "Discover, download, and run thousands of cutting edge LLMs in a few clicks.",
+ },
+];
export default function EmbeddingPreference({
setHeader,
@@ -42,45 +90,6 @@ export default function EmbeddingPreference({
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.",
- },
- ];
-
function handleForward() {
if (hiddenSubmitButtonRef.current) {
hiddenSubmitButtonRef.current.click();
@@ -161,8 +170,9 @@ export default function EmbeddingPreference({
{selectedEmbedder &&
- EMBEDDERS.find((embedder) => embedder.value === selectedEmbedder)
- ?.options}
+ EMBEDDERS.find(
+ (embedder) => embedder.value === selectedEmbedder
+ )?.options(settings)}
### Additional Information
-Add any other context about the Pull Request here that was not captured above.
+
### Developer Validations
diff --git a/server/.env.example b/server/.env.example
index 47cda159e..131dcf895 100644
--- a/server/.env.example
+++ b/server/.env.example
@@ -86,6 +86,11 @@ JWT_SECRET="my-random-string-for-seeding" # Please generate random string at lea
# EMBEDDING_MODEL_PREF='nomic-embed-text:latest'
# EMBEDDING_MODEL_MAX_CHUNK_LENGTH=8192
+# EMBEDDING_ENGINE='lmstudio'
+# EMBEDDING_BASE_PATH='https://localhost:1234/v1'
+# EMBEDDING_MODEL_PREF='nomic-ai/nomic-embed-text-v1.5-GGUF/nomic-embed-text-v1.5.Q4_0.gguf'
+# EMBEDDING_MODEL_MAX_CHUNK_LENGTH=8192
+
###########################################
######## Vector Database Selection ########
###########################################
diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js
index 958d02d66..b00b00ca2 100644
--- a/server/models/systemSettings.js
+++ b/server/models/systemSettings.js
@@ -91,6 +91,7 @@ const SystemSettings = {
},
},
currentSettings: async function () {
+ const { hasVectorCachedFiles } = require("../utils/files");
const llmProvider = process.env.LLM_PROVIDER;
const vectorDB = process.env.VECTOR_DB;
return {
@@ -108,7 +109,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/package.json b/server/package.json
index d4587eb20..752308c03 100644
--- a/server/package.json
+++ b/server/package.json
@@ -23,7 +23,7 @@
"@anthropic-ai/sdk": "^0.16.1",
"@azure/openai": "1.0.0-beta.10",
"@datastax/astra-db-ts": "^0.1.3",
- "@google/generative-ai": "^0.1.3",
+ "@google/generative-ai": "^0.7.1",
"@googleapis/youtube": "^9.0.0",
"@pinecone-database/pinecone": "^2.0.1",
"@prisma/client": "5.3.1",
diff --git a/server/utils/AiProviders/gemini/index.js b/server/utils/AiProviders/gemini/index.js
index 35885a2c6..354c1899e 100644
--- a/server/utils/AiProviders/gemini/index.js
+++ b/server/utils/AiProviders/gemini/index.js
@@ -14,7 +14,13 @@ class GeminiLLM {
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
this.model =
modelPreference || process.env.GEMINI_LLM_MODEL_PREF || "gemini-pro";
- this.gemini = genAI.getGenerativeModel({ model: this.model });
+ this.gemini = genAI.getGenerativeModel(
+ { model: this.model },
+ {
+ // Gemini-1.5-pro is only available on the v1beta API.
+ apiVersion: this.model === "gemini-1.5-pro-latest" ? "v1beta" : "v1",
+ }
+ );
this.limits = {
history: this.promptWindowLimit() * 0.15,
system: this.promptWindowLimit() * 0.15,
@@ -49,13 +55,15 @@ class GeminiLLM {
switch (this.model) {
case "gemini-pro":
return 30_720;
+ case "gemini-1.5-pro-latest":
+ return 1_048_576;
default:
return 30_720; // assume a gemini-pro model
}
}
isValidChatCompletionModel(modelName = "") {
- const validModels = ["gemini-pro"];
+ const validModels = ["gemini-pro", "gemini-1.5-pro-latest"];
return validModels.includes(modelName);
}
@@ -90,11 +98,11 @@ class GeminiLLM {
const allMessages = messages
.map((message) => {
if (message.role === "system")
- return { role: "user", parts: message.content };
+ return { role: "user", parts: [{ text: message.content }] };
if (message.role === "user")
- return { role: "user", parts: message.content };
+ return { role: "user", parts: [{ text: message.content }] };
if (message.role === "assistant")
- return { role: "model", parts: message.content };
+ return { role: "model", parts: [{ text: message.content }] };
return null;
})
.filter((msg) => !!msg);
diff --git a/server/utils/AiProviders/togetherAi/models.js b/server/utils/AiProviders/togetherAi/models.js
index 6fad3969b..79ab93bab 100644
--- a/server/utils/AiProviders/togetherAi/models.js
+++ b/server/utils/AiProviders/togetherAi/models.js
@@ -39,7 +39,7 @@ const MODELS = {
id: "databricks/dbrx-instruct",
organization: "databricks",
name: "DBRX Instruct",
- maxLength: 32000,
+ maxLength: 32768,
},
"deepseek-ai/deepseek-coder-33b-instruct": {
id: "deepseek-ai/deepseek-coder-33b-instruct",
@@ -131,6 +131,24 @@ const MODELS = {
name: "LLaMA-2 Chat (7B)",
maxLength: 4096,
},
+ "meta-llama/Llama-3-8b-chat-hf": {
+ id: "meta-llama/Llama-3-8b-chat-hf",
+ organization: "Meta",
+ name: "LLaMA-3 Chat (8B)",
+ maxLength: 8000,
+ },
+ "meta-llama/Llama-3-70b-chat-hf": {
+ id: "meta-llama/Llama-3-70b-chat-hf",
+ organization: "Meta",
+ name: "LLaMA-3 Chat (70B)",
+ maxLength: 8000,
+ },
+ "microsoft/WizardLM-2-8x22B": {
+ id: "microsoft/WizardLM-2-8x22B",
+ organization: "Microsoft",
+ name: "WizardLM-2 (8x22B)",
+ maxLength: 65536,
+ },
"mistralai/Mistral-7B-Instruct-v0.1": {
id: "mistralai/Mistral-7B-Instruct-v0.1",
organization: "mistralai",
@@ -149,6 +167,12 @@ const MODELS = {
name: "Mixtral-8x7B Instruct (46.7B)",
maxLength: 32768,
},
+ "mistralai/Mixtral-8x22B-Instruct-v0.1": {
+ id: "mistralai/Mixtral-8x22B-Instruct-v0.1",
+ organization: "mistralai",
+ name: "Mixtral-8x22B Instruct (141B)",
+ maxLength: 65536,
+ },
"NousResearch/Nous-Capybara-7B-V1p9": {
id: "NousResearch/Nous-Capybara-7B-V1p9",
organization: "NousResearch",
diff --git a/server/utils/AiProviders/togetherAi/scripts/chat_models.txt b/server/utils/AiProviders/togetherAi/scripts/chat_models.txt
index 03f0414cb..499d23549 100644
--- a/server/utils/AiProviders/togetherAi/scripts/chat_models.txt
+++ b/server/utils/AiProviders/togetherAi/scripts/chat_models.txt
@@ -6,7 +6,7 @@
| Allen AI | OLMo (7B) | allenai/OLMo-7B | 2048 |
| Austism | Chronos Hermes (13B) | Austism/chronos-hermes-13b | 2048 |
| cognitivecomputations | Dolphin 2.5 Mixtral 8x7b | cognitivecomputations/dolphin-2.5-mixtral-8x7b | 32768 |
-| databricks | DBRX Instruct | databricks/dbrx-instruct | 32000 |
+| databricks | DBRX Instruct | databricks/dbrx-instruct | 32768 |
| DeepSeek | Deepseek Coder Instruct (33B) | deepseek-ai/deepseek-coder-33b-instruct | 16384 |
| DeepSeek | DeepSeek LLM Chat (67B) | deepseek-ai/deepseek-llm-67b-chat | 4096 |
| garage-bAInd | Platypus2 Instruct (70B) | garage-bAInd/Platypus2-70B-instruct | 4096 |
@@ -22,9 +22,13 @@
| Meta | LLaMA-2 Chat (70B) | meta-llama/Llama-2-70b-chat-hf | 4096 |
| Meta | LLaMA-2 Chat (13B) | meta-llama/Llama-2-13b-chat-hf | 4096 |
| Meta | LLaMA-2 Chat (7B) | meta-llama/Llama-2-7b-chat-hf | 4096 |
+| Meta | LLaMA-3 Chat (8B) | meta-llama/Llama-3-8b-chat-hf | 8000 |
+| Meta | LLaMA-3 Chat (70B) | meta-llama/Llama-3-70b-chat-hf | 8000 |
+| Microsoft | WizardLM-2 (8x22B) | microsoft/WizardLM-2-8x22B | 65536 |
| mistralai | Mistral (7B) Instruct | mistralai/Mistral-7B-Instruct-v0.1 | 8192 |
| mistralai | Mistral (7B) Instruct v0.2 | mistralai/Mistral-7B-Instruct-v0.2 | 32768 |
| mistralai | Mixtral-8x7B Instruct (46.7B) | mistralai/Mixtral-8x7B-Instruct-v0.1 | 32768 |
+| mistralai | Mixtral-8x22B Instruct (141B) | mistralai/Mixtral-8x22B-Instruct-v0.1 | 65536 |
| NousResearch | Nous Capybara v1.9 (7B) | NousResearch/Nous-Capybara-7B-V1p9 | 8192 |
| NousResearch | Nous Hermes 2 - Mistral DPO (7B) | NousResearch/Nous-Hermes-2-Mistral-7B-DPO | 32768 |
| NousResearch | Nous Hermes 2 - Mixtral 8x7B-DPO (46.7B) | NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO | 32768 |
diff --git a/server/utils/AiProviders/togetherAi/scripts/parse.mjs b/server/utils/AiProviders/togetherAi/scripts/parse.mjs
index b78404012..7d5d6277c 100644
--- a/server/utils/AiProviders/togetherAi/scripts/parse.mjs
+++ b/server/utils/AiProviders/togetherAi/scripts/parse.mjs
@@ -8,7 +8,7 @@
// copy outputs into the export in ../models.js
// Update the date below if you run this again because TogetherAI added new models.
-// Last Collected: Apr 14, 2024
+// Last Collected: Apr 18, 2024
// Since last collection Together's docs are broken. I just copied the HTML table
// and had claude3 convert to markdown and it works well enough.
diff --git a/server/utils/EmbeddingEngines/lmstudio/index.js b/server/utils/EmbeddingEngines/lmstudio/index.js
new file mode 100644
index 000000000..b19ea2622
--- /dev/null
+++ b/server/utils/EmbeddingEngines/lmstudio/index.js
@@ -0,0 +1,110 @@
+const { maximumChunkLength } = require("../../helpers");
+
+class LMStudioEmbedder {
+ constructor() {
+ if (!process.env.EMBEDDING_BASE_PATH)
+ throw new Error("No embedding base path was set.");
+ if (!process.env.EMBEDDING_MODEL_PREF)
+ throw new Error("No embedding model was set.");
+ this.basePath = `${process.env.EMBEDDING_BASE_PATH}/embeddings`;
+ this.model = process.env.EMBEDDING_MODEL_PREF;
+
+ // 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 = 1;
+ this.embeddingMaxChunkLength = maximumChunkLength();
+ }
+
+ log(text, ...args) {
+ console.log(`\x1b[36m[${this.constructor.name}]\x1b[0m ${text}`, ...args);
+ }
+
+ async #isAlive() {
+ return await fetch(`${this.basePath}/models`, {
+ method: "HEAD",
+ })
+ .then((res) => res.ok)
+ .catch((e) => {
+ this.log(e.message);
+ return false;
+ });
+ }
+
+ async embedTextInput(textInput) {
+ const result = await this.embedChunks(textInput);
+ return result?.[0] || [];
+ }
+
+ async embedChunks(textChunks = []) {
+ if (!(await this.#isAlive()))
+ throw new Error(
+ `LMStudio service could not be reached. Is LMStudio running?`
+ );
+
+ this.log(
+ `Embedding ${textChunks.length} chunks of text with ${this.model}.`
+ );
+
+ // LMStudio will drop all queued requests now? So if there are many going on
+ // we need to do them sequentially or else only the first resolves and the others
+ // get dropped or go unanswered >:(
+ let results = [];
+ let hasError = false;
+ for (const chunk of textChunks) {
+ if (hasError) break; // If an error occurred don't continue and exit early.
+ results.push(
+ await fetch(this.basePath, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ model: this.model,
+ input: chunk,
+ }),
+ })
+ .then((res) => res.json())
+ .then((json) => {
+ const embedding = json.data[0].embedding;
+ if (!Array.isArray(embedding) || !embedding.length)
+ throw {
+ type: "EMPTY_ARR",
+ message: "The embedding was empty from LMStudio",
+ };
+ return { data: embedding, error: null };
+ })
+ .catch((error) => {
+ hasError = true;
+ return { data: [], error };
+ })
+ );
+ }
+
+ // Accumulate errors from embedding.
+ // If any are present throw an abort error.
+ const errors = results
+ .filter((res) => !!res.error)
+ .map((res) => res.error)
+ .flat();
+
+ if (errors.length > 0) {
+ let uniqueErrors = new Set();
+ console.log(errors);
+ errors.map((error) =>
+ uniqueErrors.add(`[${error.type}]: ${error.message}`)
+ );
+
+ if (errors.length > 0)
+ throw new Error(
+ `LMStudio Failed to embed: ${Array.from(uniqueErrors).join(", ")}`
+ );
+ }
+
+ const data = results.map((res) => res?.data || []);
+ return data.length > 0 ? data : null;
+ }
+}
+
+module.exports = {
+ LMStudioEmbedder,
+};
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,
};
diff --git a/server/utils/helpers/index.js b/server/utils/helpers/index.js
index 3d8bb915f..837a28f60 100644
--- a/server/utils/helpers/index.js
+++ b/server/utils/helpers/index.js
@@ -102,6 +102,9 @@ function getEmbeddingEngineSelection() {
case "native":
const { NativeEmbedder } = require("../EmbeddingEngines/native");
return new NativeEmbedder();
+ case "lmstudio":
+ const { LMStudioEmbedder } = require("../EmbeddingEngines/lmstudio");
+ return new LMStudioEmbedder();
default:
return null;
}
diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js
index 9eb9a8e53..ed2318f84 100644
--- a/server/utils/helpers/updateENV.js
+++ b/server/utils/helpers/updateENV.js
@@ -387,7 +387,7 @@ function supportedTranscriptionProvider(input = "") {
}
function validGeminiModel(input = "") {
- const validModels = ["gemini-pro"];
+ const validModels = ["gemini-pro", "gemini-1.5-pro-latest"];
return validModels.includes(input)
? null
: `Invalid Model type. Must be one of ${validModels.join(", ")}.`;
@@ -408,7 +408,14 @@ function validAnthropicModel(input = "") {
}
function supportedEmbeddingModel(input = "") {
- const supported = ["openai", "azure", "localai", "native", "ollama"];
+ const supported = [
+ "openai",
+ "azure",
+ "localai",
+ "native",
+ "ollama",
+ "lmstudio",
+ ];
return supported.includes(input)
? null
: `Invalid Embedding model type. Must be one of ${supported.join(", ")}.`;
diff --git a/server/yarn.lock b/server/yarn.lock
index 466ac1560..8e9d1010c 100644
--- a/server/yarn.lock
+++ b/server/yarn.lock
@@ -220,10 +220,10 @@
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
-"@google/generative-ai@^0.1.3":
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/@google/generative-ai/-/generative-ai-0.1.3.tgz#8e529d4d86c85b64d297b4abf1a653d613a09a9f"
- integrity sha512-Cm4uJX1sKarpm1mje/MiOIinM7zdUUrQp/5/qGPAgznbdd/B9zup5ehT6c1qGqycFcSopTA1J1HpqHS5kJR8hQ==
+"@google/generative-ai@^0.7.1":
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/@google/generative-ai/-/generative-ai-0.7.1.tgz#eb187c75080c0706245699dbc06816c830d8c6a7"
+ integrity sha512-WTjMLLYL/xfA5BW6xAycRPiAX7FNHKAxrid/ayqC1QMam0KAK0NbMeS9Lubw80gVg5xFMLE+H7pw4wdNzTOlxw==
"@googleapis/youtube@^9.0.0":
version "9.0.0"