mirror of
https://github.com/Mintplex-Labs/anything-llm.git
synced 2025-04-17 18:18:11 +00:00
parent
910eb36cfe
commit
0b845fbb1c
23 changed files with 52 additions and 164 deletions
server/utils
AiProviders
anthropic
azureOpenAi
cohere
gemini
genericOpenAi
groq
huggingface
koboldCPP
liteLLM
lmStudio
localAi
mistral
native
ollama
openAi
openRouter
perplexity
textGenWebUI
togetherAi
chats
helpers
|
@ -66,13 +66,6 @@ class AnthropicLLM {
|
|||
return validModels.includes(modelName);
|
||||
}
|
||||
|
||||
// Moderation can be done with Anthropic, but its not really "exact" so we skip it
|
||||
// https://docs.anthropic.com/claude/docs/content-moderation
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
constructPrompt({
|
||||
systemPrompt = "",
|
||||
contextTexts = [],
|
||||
|
|
|
@ -72,11 +72,6 @@ class AzureOpenAiLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented by Azure OpenAI so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = [], { temperature = 0.7 }) {
|
||||
if (!this.model)
|
||||
throw new Error(
|
||||
|
|
|
@ -102,11 +102,6 @@ class CohereLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
if (!(await this.isValidChatCompletionModel(this.model)))
|
||||
throw new Error(
|
||||
|
|
|
@ -112,12 +112,6 @@ class GeminiLLM {
|
|||
return validModels.includes(modelName);
|
||||
}
|
||||
|
||||
// Moderation cannot be done with Gemini.
|
||||
// Not implemented so must be stubbed
|
||||
async isSafe(_input = "") {
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
constructPrompt({
|
||||
systemPrompt = "",
|
||||
contextTexts = [],
|
||||
|
|
|
@ -83,11 +83,6 @@ class GenericOpenAiLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
const result = await this.openai.chat.completions
|
||||
.create({
|
||||
|
|
|
@ -85,11 +85,6 @@ class GroqLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
if (!(await this.isValidChatCompletionModel(this.model)))
|
||||
throw new Error(
|
||||
|
|
|
@ -79,11 +79,6 @@ class HuggingFaceLLM {
|
|||
];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
const result = await this.openai.createChatCompletion({
|
||||
model: this.model,
|
||||
|
|
|
@ -79,11 +79,6 @@ class KoboldCPPLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
const result = await this.openai.chat.completions
|
||||
.create({
|
||||
|
|
|
@ -78,11 +78,6 @@ class LiteLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
const result = await this.openai.chat.completions
|
||||
.create({
|
||||
|
|
|
@ -76,11 +76,6 @@ class LMStudioLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
if (!this.model)
|
||||
throw new Error(
|
||||
|
|
|
@ -66,11 +66,6 @@ class LocalAiLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
if (!(await this.isValidChatCompletionModel(this.model)))
|
||||
throw new Error(
|
||||
|
|
|
@ -62,10 +62,6 @@ class MistralLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_ = "") {
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
if (!(await this.isValidChatCompletionModel(this.model)))
|
||||
throw new Error(
|
||||
|
|
|
@ -117,11 +117,6 @@ class NativeLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
const model = await this.#llamaClient({ temperature });
|
||||
const response = await model.call(messages);
|
||||
|
|
|
@ -99,11 +99,6 @@ class OllamaAILLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
const model = this.#ollamaClient({ temperature });
|
||||
const textResponse = await model
|
||||
|
|
|
@ -86,37 +86,6 @@ class OpenAiLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(input = "") {
|
||||
const { flagged = false, categories = {} } = await this.openai.moderations
|
||||
.create({ input })
|
||||
.then((res) => {
|
||||
if (!res.hasOwnProperty("results"))
|
||||
throw new Error("OpenAI moderation: No results!");
|
||||
if (res.results.length === 0)
|
||||
throw new Error("OpenAI moderation: No results length!");
|
||||
return res.results[0];
|
||||
})
|
||||
.catch((error) => {
|
||||
throw new Error(
|
||||
`OpenAI::CreateModeration failed with: ${error.message}`
|
||||
);
|
||||
});
|
||||
|
||||
if (!flagged) return { safe: true, reasons: [] };
|
||||
const reasons = Object.keys(categories)
|
||||
.map((category) => {
|
||||
const value = categories[category];
|
||||
if (value === true) {
|
||||
return category.replace("/", " or ");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter((reason) => !!reason);
|
||||
|
||||
return { safe: false, reasons };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
if (!(await this.isValidChatCompletionModel(this.model)))
|
||||
throw new Error(
|
||||
|
|
|
@ -124,11 +124,6 @@ class OpenRouterLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
if (!(await this.isValidChatCompletionModel(this.model)))
|
||||
throw new Error(
|
||||
|
|
|
@ -75,11 +75,6 @@ class PerplexityLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
if (!(await this.isValidChatCompletionModel(this.model)))
|
||||
throw new Error(
|
||||
|
|
|
@ -76,11 +76,6 @@ class TextGenWebUILLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
const result = await this.openai.chat.completions
|
||||
.create({
|
||||
|
|
|
@ -73,11 +73,6 @@ class TogetherAiLLM {
|
|||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
|
||||
}
|
||||
|
||||
async isSafe(_input = "") {
|
||||
// Not implemented so must be stubbed
|
||||
return { safe: true, reasons: [] };
|
||||
}
|
||||
|
||||
async getChatCompletion(messages = null, { temperature = 0.7 }) {
|
||||
if (!(await this.isValidChatCompletionModel(this.model)))
|
||||
throw new Error(
|
||||
|
|
|
@ -33,20 +33,6 @@ async function streamChatWithForEmbed(
|
|||
model: chatModel ?? embed.workspace?.chatModel,
|
||||
});
|
||||
const VectorDb = getVectorDbClass();
|
||||
const { safe, reasons = [] } = await LLMConnector.isSafe(message);
|
||||
if (!safe) {
|
||||
writeResponseChunk(response, {
|
||||
id: uuid,
|
||||
type: "abort",
|
||||
textResponse: null,
|
||||
sources: [],
|
||||
close: true,
|
||||
error: `This message was moderated and will not be allowed. Violations for ${reasons.join(
|
||||
", "
|
||||
)} found.`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const messageLimit = 20;
|
||||
const hasVectorizedSpace = await VectorDb.hasNamespace(embed.workspace.slug);
|
||||
|
|
|
@ -56,19 +56,6 @@ async function chatWithWorkspace(
|
|||
model: workspace?.chatModel,
|
||||
});
|
||||
const VectorDb = getVectorDbClass();
|
||||
const { safe, reasons = [] } = await LLMConnector.isSafe(message);
|
||||
if (!safe) {
|
||||
return {
|
||||
id: uuid,
|
||||
type: "abort",
|
||||
textResponse: null,
|
||||
sources: [],
|
||||
close: true,
|
||||
error: `This message was moderated and will not be allowed. Violations for ${reasons.join(
|
||||
", "
|
||||
)} found.`,
|
||||
};
|
||||
}
|
||||
|
||||
const messageLimit = workspace?.openAiHistory || 20;
|
||||
const hasVectorizedSpace = await VectorDb.hasNamespace(workspace.slug);
|
||||
|
|
|
@ -53,20 +53,6 @@ async function streamChatWithWorkspace(
|
|||
model: workspace?.chatModel,
|
||||
});
|
||||
const VectorDb = getVectorDbClass();
|
||||
const { safe, reasons = [] } = await LLMConnector.isSafe(message);
|
||||
if (!safe) {
|
||||
writeResponseChunk(response, {
|
||||
id: uuid,
|
||||
type: "abort",
|
||||
textResponse: null,
|
||||
sources: [],
|
||||
close: true,
|
||||
error: `This message was moderated and will not be allowed. Violations for ${reasons.join(
|
||||
", "
|
||||
)} found.`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const messageLimit = workspace?.openAiHistory || 20;
|
||||
const hasVectorizedSpace = await VectorDb.hasNamespace(workspace.slug);
|
||||
|
|
|
@ -1,3 +1,46 @@
|
|||
/**
|
||||
* @typedef {Object} BaseLLMProvider - A basic llm provider object
|
||||
* @property {Function} streamingEnabled - Checks if streaming is enabled for chat completions.
|
||||
* @property {Function} promptWindowLimit - Returns the token limit for the current model.
|
||||
* @property {Function} isValidChatCompletionModel - Validates if the provided model is suitable for chat completion.
|
||||
* @property {Function} constructPrompt - Constructs a formatted prompt for the chat completion request.
|
||||
* @property {Function} getChatCompletion - Gets a chat completion response from OpenAI.
|
||||
* @property {Function} streamGetChatCompletion - Streams a chat completion response from OpenAI.
|
||||
* @property {Function} handleStream - Handles the streaming response.
|
||||
* @property {Function} embedTextInput - Embeds the provided text input using the specified embedder.
|
||||
* @property {Function} embedChunks - Embeds multiple chunks of text using the specified embedder.
|
||||
* @property {Function} compressMessages - Compresses chat messages to fit within the token limit.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} BaseVectorDatabaseProvider
|
||||
* @property {string} name - The name of the Vector Database instance.
|
||||
* @property {Function} connect - Connects to the Vector Database client.
|
||||
* @property {Function} totalVectors - Returns the total number of vectors in the database.
|
||||
* @property {Function} namespaceCount - Returns the count of vectors in a given namespace.
|
||||
* @property {Function} similarityResponse - Performs a similarity search on a given namespace.
|
||||
* @property {Function} namespace - Retrieves the specified namespace collection.
|
||||
* @property {Function} hasNamespace - Checks if a namespace exists.
|
||||
* @property {Function} namespaceExists - Verifies if a namespace exists in the client.
|
||||
* @property {Function} deleteVectorsInNamespace - Deletes all vectors in a specified namespace.
|
||||
* @property {Function} deleteDocumentFromNamespace - Deletes a document from a specified namespace.
|
||||
* @property {Function} addDocumentToNamespace - Adds a document to a specified namespace.
|
||||
* @property {Function} performSimilaritySearch - Performs a similarity search in the namespace.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} BaseEmbedderProvider
|
||||
* @property {string} model - The model used for embedding.
|
||||
* @property {number} maxConcurrentChunks - The maximum number of chunks processed concurrently.
|
||||
* @property {number} embeddingMaxChunkLength - The maximum length of each chunk for embedding.
|
||||
* @property {Function} embedTextInput - Embeds a single text input.
|
||||
* @property {Function} embedChunks - Embeds multiple chunks of text.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the systems current vector database provider.
|
||||
* @returns { BaseVectorDatabaseProvider}
|
||||
*/
|
||||
function getVectorDbClass() {
|
||||
const vectorSelection = process.env.VECTOR_DB || "lancedb";
|
||||
switch (vectorSelection) {
|
||||
|
@ -30,6 +73,11 @@ function getVectorDbClass() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the LLMProvider with its embedder attached via system or via defined provider.
|
||||
* @param {{provider: string | null, model: string | null} | null} params - Initialize params for LLMs provider
|
||||
* @returns {BaseLLMProvider}
|
||||
*/
|
||||
function getLLMProvider({ provider = null, model = null } = {}) {
|
||||
const LLMSelection = provider ?? process.env.LLM_PROVIDER ?? "openai";
|
||||
const embedder = getEmbeddingEngineSelection();
|
||||
|
@ -99,6 +147,10 @@ function getLLMProvider({ provider = null, model = null } = {}) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the EmbedderProvider by itself to whatever is currently in the system settings.
|
||||
* @returns {BaseEmbedderProvider}
|
||||
*/
|
||||
function getEmbeddingEngineSelection() {
|
||||
const { NativeEmbedder } = require("../EmbeddingEngines/native");
|
||||
const engineSelection = process.env.EMBEDDING_ENGINE;
|
||||
|
|
Loading…
Add table
Reference in a new issue