You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

373 lines
15 KiB

11 months ago
  1. /**
  2. * File Attachment for automatic upload on the chat container page.
  3. * @typedef Attachment
  4. * @property {string} name - the given file name
  5. * @property {string} mime - the given file mime
  6. * @property {string} contentString - full base64 encoded string of file
  7. */
  8. /**
  9. * @typedef {Object} ResponseMetrics
  10. * @property {number} prompt_tokens - The number of prompt tokens used
  11. * @property {number} completion_tokens - The number of completion tokens used
  12. * @property {number} total_tokens - The total number of tokens used
  13. * @property {number} outputTps - The output tokens per second
  14. * @property {number} duration - The duration of the request in seconds
  15. *
  16. * @typedef {Object} ChatMessage
  17. * @property {string} role - The role of the message sender (e.g. 'user', 'assistant', 'system')
  18. * @property {string} content - The content of the message
  19. *
  20. * @typedef {Object} ChatCompletionResponse
  21. * @property {string} textResponse - The text response from the LLM
  22. * @property {ResponseMetrics} metrics - The response metrics
  23. *
  24. * @typedef {Object} ChatCompletionOptions
  25. * @property {number} temperature - The sampling temperature for the LLM response
  26. *
  27. * @typedef {function(Array<ChatMessage>, ChatCompletionOptions): Promise<ChatCompletionResponse>} getChatCompletionFunction
  28. *
  29. * @typedef {function(Array<ChatMessage>, ChatCompletionOptions): Promise<import("./chat/LLMPerformanceMonitor").MonitoredStream>} streamGetChatCompletionFunction
  30. */
  31. /**
  32. * @typedef {Object} BaseLLMProvider - A basic llm provider object
  33. * @property {Function} streamingEnabled - Checks if streaming is enabled for chat completions.
  34. * @property {Function} promptWindowLimit - Returns the token limit for the current model.
  35. * @property {Function} isValidChatCompletionModel - Validates if the provided model is suitable for chat completion.
  36. * @property {Function} constructPrompt - Constructs a formatted prompt for the chat completion request.
  37. * @property {getChatCompletionFunction} getChatCompletion - Gets a chat completion response from OpenAI.
  38. * @property {streamGetChatCompletionFunction} streamGetChatCompletion - Streams a chat completion response from OpenAI.
  39. * @property {Function} handleStream - Handles the streaming response.
  40. * @property {Function} embedTextInput - Embeds the provided text input using the specified embedder.
  41. * @property {Function} embedChunks - Embeds multiple chunks of text using the specified embedder.
  42. * @property {Function} compressMessages - Compresses chat messages to fit within the token limit.
  43. */
  44. /**
  45. * @typedef {Object} BaseLLMProviderClass - Class method of provider - not instantiated
  46. * @property {function(string): number} promptWindowLimit - Returns the token limit for the provided model.
  47. */
  48. /**
  49. * @typedef {Object} BaseVectorDatabaseProvider
  50. * @property {string} name - The name of the Vector Database instance.
  51. * @property {Function} connect - Connects to the Vector Database client.
  52. * @property {Function} totalVectors - Returns the total number of vectors in the database.
  53. * @property {Function} namespaceCount - Returns the count of vectors in a given namespace.
  54. * @property {Function} similarityResponse - Performs a similarity search on a given namespace.
  55. * @property {Function} rerankedSimilarityResponse - Performs a similarity search on a given namespace with reranking (if supported by provider).
  56. * @property {Function} namespace - Retrieves the specified namespace collection.
  57. * @property {Function} hasNamespace - Checks if a namespace exists.
  58. * @property {Function} namespaceExists - Verifies if a namespace exists in the client.
  59. * @property {Function} deleteVectorsInNamespace - Deletes all vectors in a specified namespace.
  60. * @property {Function} deleteDocumentFromNamespace - Deletes a document from a specified namespace.
  61. * @property {Function} addDocumentToNamespace - Adds a document to a specified namespace.
  62. * @property {Function} performSimilaritySearch - Performs a similarity search in the namespace.
  63. */
  64. /**
  65. * @typedef {Object} BaseEmbedderProvider
  66. * @property {string} model - The model used for embedding.
  67. * @property {number} maxConcurrentChunks - The maximum number of chunks processed concurrently.
  68. * @property {number} embeddingMaxChunkLength - The maximum length of each chunk for embedding.
  69. * @property {Function} embedTextInput - Embeds a single text input.
  70. * @property {Function} embedChunks - Embeds multiple chunks of text.
  71. */
  72. /**
  73. * Gets the systems current vector database provider.
  74. * @param {('pinecone' | 'chroma' | 'lancedb' | 'weaviate' | 'qdrant' | 'milvus' | 'zilliz' | 'astra') | null} getExactly - If provided, this will return an explit provider.
  75. * @returns { BaseVectorDatabaseProvider}
  76. */
  77. function getVectorDbClass(getExactly = null) {
  78. const vectorSelection = getExactly ?? process.env.VECTOR_DB ?? "lancedb";
  79. switch (vectorSelection) {
  80. case "pinecone":
  81. const { Pinecone } = require("../vectorDbProviders/pinecone");
  82. return Pinecone;
  83. case "chroma":
  84. const { Chroma } = require("../vectorDbProviders/chroma");
  85. return Chroma;
  86. case "lancedb":
  87. const { LanceDb } = require("../vectorDbProviders/lance");
  88. return LanceDb;
  89. case "weaviate":
  90. const { Weaviate } = require("../vectorDbProviders/weaviate");
  91. return Weaviate;
  92. case "qdrant":
  93. const { QDrant } = require("../vectorDbProviders/qdrant");
  94. return QDrant;
  95. case "milvus":
  96. const { Milvus } = require("../vectorDbProviders/milvus");
  97. return Milvus;
  98. case "zilliz":
  99. const { Zilliz } = require("../vectorDbProviders/zilliz");
  100. return Zilliz;
  101. case "astra":
  102. const { AstraDB } = require("../vectorDbProviders/astra");
  103. return AstraDB;
  104. default:
  105. throw new Error("ENV: No VECTOR_DB value found in environment!");
  106. }
  107. }
  108. /**
  109. * Returns the LLMProvider with its embedder attached via system or via defined provider.
  110. * @param {{provider: string | null, model: string | null} | null} params - Initialize params for LLMs provider
  111. * @returns {BaseLLMProvider}
  112. */
  113. function getLLMProvider({ provider = null, model = null } = {}) {
  114. const LLMSelection = provider ?? process.env.LLM_PROVIDER ?? "openai";
  115. const embedder = getEmbeddingEngineSelection();
  116. switch (LLMSelection) {
  117. case "openai":
  118. const { OpenAiLLM } = require("../AiProviders/openAi");
  119. return new OpenAiLLM(embedder, model);
  120. case "azure":
  121. const { AzureOpenAiLLM } = require("../AiProviders/azureOpenAi");
  122. return new AzureOpenAiLLM(embedder, model);
  123. case "anthropic":
  124. const { AnthropicLLM } = require("../AiProviders/anthropic");
  125. return new AnthropicLLM(embedder, model);
  126. case "gemini":
  127. const { GeminiLLM } = require("../AiProviders/gemini");
  128. return new GeminiLLM(embedder, model);
  129. case "lmstudio":
  130. const { LMStudioLLM } = require("../AiProviders/lmStudio");
  131. return new LMStudioLLM(embedder, model);
  132. case "localai":
  133. const { LocalAiLLM } = require("../AiProviders/localAi");
  134. return new LocalAiLLM(embedder, model);
  135. case "ollama":
  136. const { OllamaAILLM } = require("../AiProviders/ollama");
  137. return new OllamaAILLM(embedder, model);
  138. case "togetherai":
  139. const { TogetherAiLLM } = require("../AiProviders/togetherAi");
  140. return new TogetherAiLLM(embedder, model);
  141. case "fireworksai":
  142. const { FireworksAiLLM } = require("../AiProviders/fireworksAi");
  143. return new FireworksAiLLM(embedder, model);
  144. case "perplexity":
  145. const { PerplexityLLM } = require("../AiProviders/perplexity");
  146. return new PerplexityLLM(embedder, model);
  147. case "openrouter":
  148. const { OpenRouterLLM } = require("../AiProviders/openRouter");
  149. return new OpenRouterLLM(embedder, model);
  150. case "mistral":
  151. const { MistralLLM } = require("../AiProviders/mistral");
  152. return new MistralLLM(embedder, model);
  153. case "huggingface":
  154. const { HuggingFaceLLM } = require("../AiProviders/huggingface");
  155. return new HuggingFaceLLM(embedder, model);
  156. case "groq":
  157. const { GroqLLM } = require("../AiProviders/groq");
  158. return new GroqLLM(embedder, model);
  159. case "koboldcpp":
  160. const { KoboldCPPLLM } = require("../AiProviders/koboldCPP");
  161. return new KoboldCPPLLM(embedder, model);
  162. case "textgenwebui":
  163. const { TextGenWebUILLM } = require("../AiProviders/textGenWebUI");
  164. return new TextGenWebUILLM(embedder, model);
  165. case "cohere":
  166. const { CohereLLM } = require("../AiProviders/cohere");
  167. return new CohereLLM(embedder, model);
  168. case "litellm":
  169. const { LiteLLM } = require("../AiProviders/liteLLM");
  170. return new LiteLLM(embedder, model);
  171. case "generic-openai":
  172. const { GenericOpenAiLLM } = require("../AiProviders/genericOpenAi");
  173. return new GenericOpenAiLLM(embedder, model);
  174. case "bedrock":
  175. const { AWSBedrockLLM } = require("../AiProviders/bedrock");
  176. return new AWSBedrockLLM(embedder, model);
  177. case "deepseek":
  178. const { DeepSeekLLM } = require("../AiProviders/deepseek");
  179. return new DeepSeekLLM(embedder, model);
  180. case "apipie":
  181. const { ApiPieLLM } = require("../AiProviders/apipie");
  182. return new ApiPieLLM(embedder, model);
  183. case "novita":
  184. const { NovitaLLM } = require("../AiProviders/novita");
  185. return new NovitaLLM(embedder, model);
  186. case "xai":
  187. const { XAiLLM } = require("../AiProviders/xai");
  188. return new XAiLLM(embedder, model);
  189. case "nvidia-nim":
  190. const { NvidiaNimLLM } = require("../AiProviders/nvidiaNim");
  191. return new NvidiaNimLLM(embedder, model);
  192. default:
  193. throw new Error(
  194. `ENV: No valid LLM_PROVIDER value found in environment! Using ${process.env.LLM_PROVIDER}`
  195. );
  196. }
  197. }
  198. /**
  199. * Returns the EmbedderProvider by itself to whatever is currently in the system settings.
  200. * @returns {BaseEmbedderProvider}
  201. */
  202. function getEmbeddingEngineSelection() {
  203. const { NativeEmbedder } = require("../EmbeddingEngines/native");
  204. const engineSelection = process.env.EMBEDDING_ENGINE;
  205. switch (engineSelection) {
  206. case "openai":
  207. const { OpenAiEmbedder } = require("../EmbeddingEngines/openAi");
  208. return new OpenAiEmbedder();
  209. case "azure":
  210. const {
  211. AzureOpenAiEmbedder,
  212. } = require("../EmbeddingEngines/azureOpenAi");
  213. return new AzureOpenAiEmbedder();
  214. case "localai":
  215. const { LocalAiEmbedder } = require("../EmbeddingEngines/localAi");
  216. return new LocalAiEmbedder();
  217. case "ollama":
  218. const { OllamaEmbedder } = require("../EmbeddingEngines/ollama");
  219. return new OllamaEmbedder();
  220. case "native":
  221. return new NativeEmbedder();
  222. case "lmstudio":
  223. const { LMStudioEmbedder } = require("../EmbeddingEngines/lmstudio");
  224. return new LMStudioEmbedder();
  225. case "cohere":
  226. const { CohereEmbedder } = require("../EmbeddingEngines/cohere");
  227. return new CohereEmbedder();
  228. case "voyageai":
  229. const { VoyageAiEmbedder } = require("../EmbeddingEngines/voyageAi");
  230. return new VoyageAiEmbedder();
  231. case "litellm":
  232. const { LiteLLMEmbedder } = require("../EmbeddingEngines/liteLLM");
  233. return new LiteLLMEmbedder();
  234. case "mistral":
  235. const { MistralEmbedder } = require("../EmbeddingEngines/mistral");
  236. return new MistralEmbedder();
  237. case "generic-openai":
  238. const {
  239. GenericOpenAiEmbedder,
  240. } = require("../EmbeddingEngines/genericOpenAi");
  241. return new GenericOpenAiEmbedder();
  242. case "gemini":
  243. const { GeminiEmbedder } = require("../EmbeddingEngines/gemini");
  244. return new GeminiEmbedder();
  245. default:
  246. return new NativeEmbedder();
  247. }
  248. }
  249. /**
  250. * Returns the LLMProviderClass - this is a helper method to access static methods on a class
  251. * @param {{provider: string | null} | null} params - Initialize params for LLMs provider
  252. * @returns {BaseLLMProviderClass}
  253. */
  254. function getLLMProviderClass({ provider = null } = {}) {
  255. switch (provider) {
  256. case "openai":
  257. const { OpenAiLLM } = require("../AiProviders/openAi");
  258. return OpenAiLLM;
  259. case "azure":
  260. const { AzureOpenAiLLM } = require("../AiProviders/azureOpenAi");
  261. return AzureOpenAiLLM;
  262. case "anthropic":
  263. const { AnthropicLLM } = require("../AiProviders/anthropic");
  264. return AnthropicLLM;
  265. case "gemini":
  266. const { GeminiLLM } = require("../AiProviders/gemini");
  267. return GeminiLLM;
  268. case "lmstudio":
  269. const { LMStudioLLM } = require("../AiProviders/lmStudio");
  270. return LMStudioLLM;
  271. case "localai":
  272. const { LocalAiLLM } = require("../AiProviders/localAi");
  273. return LocalAiLLM;
  274. case "ollama":
  275. const { OllamaAILLM } = require("../AiProviders/ollama");
  276. return OllamaAILLM;
  277. case "togetherai":
  278. const { TogetherAiLLM } = require("../AiProviders/togetherAi");
  279. return TogetherAiLLM;
  280. case "fireworksai":
  281. const { FireworksAiLLM } = require("../AiProviders/fireworksAi");
  282. return FireworksAiLLM;
  283. case "perplexity":
  284. const { PerplexityLLM } = require("../AiProviders/perplexity");
  285. return PerplexityLLM;
  286. case "openrouter":
  287. const { OpenRouterLLM } = require("../AiProviders/openRouter");
  288. return OpenRouterLLM;
  289. case "mistral":
  290. const { MistralLLM } = require("../AiProviders/mistral");
  291. return MistralLLM;
  292. case "huggingface":
  293. const { HuggingFaceLLM } = require("../AiProviders/huggingface");
  294. return HuggingFaceLLM;
  295. case "groq":
  296. const { GroqLLM } = require("../AiProviders/groq");
  297. return GroqLLM;
  298. case "koboldcpp":
  299. const { KoboldCPPLLM } = require("../AiProviders/koboldCPP");
  300. return KoboldCPPLLM;
  301. case "textgenwebui":
  302. const { TextGenWebUILLM } = require("../AiProviders/textGenWebUI");
  303. return TextGenWebUILLM;
  304. case "cohere":
  305. const { CohereLLM } = require("../AiProviders/cohere");
  306. return CohereLLM;
  307. case "litellm":
  308. const { LiteLLM } = require("../AiProviders/liteLLM");
  309. return LiteLLM;
  310. case "generic-openai":
  311. const { GenericOpenAiLLM } = require("../AiProviders/genericOpenAi");
  312. return GenericOpenAiLLM;
  313. case "bedrock":
  314. const { AWSBedrockLLM } = require("../AiProviders/bedrock");
  315. return AWSBedrockLLM;
  316. case "deepseek":
  317. const { DeepSeekLLM } = require("../AiProviders/deepseek");
  318. return DeepSeekLLM;
  319. case "apipie":
  320. const { ApiPieLLM } = require("../AiProviders/apipie");
  321. return ApiPieLLM;
  322. case "novita":
  323. const { NovitaLLM } = require("../AiProviders/novita");
  324. return NovitaLLM;
  325. case "xai":
  326. const { XAiLLM } = require("../AiProviders/xai");
  327. return XAiLLM;
  328. case "nvidia-nim":
  329. const { NvidiaNimLLM } = require("../AiProviders/nvidiaNim");
  330. return NvidiaNimLLM;
  331. default:
  332. return null;
  333. }
  334. }
  335. // Some models have lower restrictions on chars that can be encoded in a single pass
  336. // and by default we assume it can handle 1,000 chars, but some models use work with smaller
  337. // chars so here we can override that value when embedding information.
  338. function maximumChunkLength() {
  339. if (
  340. !!process.env.EMBEDDING_MODEL_MAX_CHUNK_LENGTH &&
  341. !isNaN(process.env.EMBEDDING_MODEL_MAX_CHUNK_LENGTH) &&
  342. Number(process.env.EMBEDDING_MODEL_MAX_CHUNK_LENGTH) > 1
  343. )
  344. return Number(process.env.EMBEDDING_MODEL_MAX_CHUNK_LENGTH);
  345. return 1_000;
  346. }
  347. function toChunks(arr, size) {
  348. return Array.from({ length: Math.ceil(arr.length / size) }, (_v, i) =>
  349. arr.slice(i * size, i * size + size)
  350. );
  351. }
  352. module.exports = {
  353. getEmbeddingEngineSelection,
  354. maximumChunkLength,
  355. getVectorDbClass,
  356. getLLMProviderClass,
  357. getLLMProvider,
  358. toChunks,
  359. };