diff --git a/package.json b/package.json index 25fbde2a..1d1b2d3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flowise", - "version": "1.2.3", + "version": "1.2.4", "private": true, "homepage": "https://flowiseai.com", "workspaces": [ diff --git a/packages/components/nodes/chatmodels/ChatOpenAI/ChatOpenAI.ts b/packages/components/nodes/chatmodels/ChatOpenAI/ChatOpenAI.ts index dfb9b5d5..5d608c5e 100644 --- a/packages/components/nodes/chatmodels/ChatOpenAI/ChatOpenAI.ts +++ b/packages/components/nodes/chatmodels/ChatOpenAI/ChatOpenAI.ts @@ -1,7 +1,6 @@ -import { OpenAIChatInput } from 'langchain/llms/openai' import { INode, INodeData, INodeParams } from '../../../src/Interface' import { getBaseClasses } from '../../../src/utils' -import { ChatOpenAI } from 'langchain/chat_models/openai' +import { ChatOpenAI, OpenAIChatInput } from 'langchain/chat_models/openai' class ChatOpenAI_ChatModels implements INode { label: string diff --git a/packages/components/nodes/embeddings/CohereEmbedding/CohereEmbedding.ts b/packages/components/nodes/embeddings/CohereEmbedding/CohereEmbedding.ts index 923cf6c6..344713a4 100644 --- a/packages/components/nodes/embeddings/CohereEmbedding/CohereEmbedding.ts +++ b/packages/components/nodes/embeddings/CohereEmbedding/CohereEmbedding.ts @@ -1,6 +1,6 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface' import { getBaseClasses } from '../../../src/utils' -import { CohereEmbeddings } from 'langchain/embeddings/cohere' +import { CohereEmbeddings, CohereEmbeddingsParams } from 'langchain/embeddings/cohere' class CohereEmbedding_Embeddings implements INode { label: string @@ -25,14 +25,42 @@ class CohereEmbedding_Embeddings implements INode { label: 'Cohere API Key', name: 'cohereApiKey', type: 'password' + }, + { + label: 'Model Name', + name: 'modelName', + type: 'options', + options: [ + { + label: 'embed-english-v2.0', + name: 'embed-english-v2.0' + }, + { + label: 'embed-english-light-v2.0', + name: 'embed-english-light-v2.0' + }, + { + label: 'embed-multilingual-v2.0', + name: 'embed-multilingual-v2.0' + } + ], + default: 'embed-english-v2.0', + optional: true } ] } async init(nodeData: INodeData): Promise { const apiKey = nodeData.inputs?.cohereApiKey as string + const modelName = nodeData.inputs?.modelName as string - const model = new CohereEmbeddings({ apiKey }) + const obj: Partial & { apiKey?: string } = { + apiKey + } + + if (modelName) obj.modelName = modelName + + const model = new CohereEmbeddings(obj) return model } } diff --git a/packages/components/nodes/llms/Cohere/Cohere.ts b/packages/components/nodes/llms/Cohere/Cohere.ts new file mode 100644 index 00000000..dc632ec3 --- /dev/null +++ b/packages/components/nodes/llms/Cohere/Cohere.ts @@ -0,0 +1,97 @@ +import { INode, INodeData, INodeParams } from '../../../src/Interface' +import { getBaseClasses } from '../../../src/utils' +import { Cohere, CohereInput } from 'langchain/llms/cohere' + +class Cohere_LLMs implements INode { + label: string + name: string + type: string + icon: string + category: string + description: string + baseClasses: string[] + inputs: INodeParams[] + + constructor() { + this.label = 'Cohere' + this.name = 'cohere' + this.type = 'Cohere' + this.icon = 'cohere.png' + this.category = 'LLMs' + this.description = 'Wrapper around Cohere large language models' + this.baseClasses = [this.type, ...getBaseClasses(Cohere)] + this.inputs = [ + { + label: 'Cohere Api Key', + name: 'cohereApiKey', + type: 'password' + }, + { + label: 'Model Name', + name: 'modelName', + type: 'options', + options: [ + { + label: 'command', + name: 'command' + }, + { + label: 'command-light', + name: 'command-light' + }, + { + label: 'command-nightly', + name: 'command-nightly' + }, + { + label: 'command-light-nightly', + name: 'command-light-nightly' + }, + { + label: 'base', + name: 'base' + }, + { + label: 'base-light', + name: 'base-light' + } + ], + default: 'command', + optional: true + }, + { + label: 'Temperature', + name: 'temperature', + type: 'number', + default: 0.7, + optional: true + }, + { + label: 'Max Tokens', + name: 'maxTokens', + type: 'number', + optional: true + } + ] + } + + async init(nodeData: INodeData): Promise { + const temperature = nodeData.inputs?.temperature as string + const modelName = nodeData.inputs?.modelName as string + const apiKey = nodeData.inputs?.cohereApiKey as string + const maxTokens = nodeData.inputs?.maxTokens as string + + const obj: CohereInput = { + apiKey + } + + if (maxTokens) obj.maxTokens = parseInt(maxTokens, 10) + if (modelName) obj.model = modelName + if (temperature) obj.temperature = parseInt(temperature, 10) + + const model = new Cohere(obj) + return model + } +} + +module.exports = { nodeClass: Cohere_LLMs } diff --git a/packages/components/nodes/llms/Cohere/cohere.png b/packages/components/nodes/llms/Cohere/cohere.png new file mode 100644 index 00000000..266adeac Binary files /dev/null and b/packages/components/nodes/llms/Cohere/cohere.png differ diff --git a/packages/components/nodes/textsplitters/CharacterTextSplitter/CharacterTextSplitter.ts b/packages/components/nodes/textsplitters/CharacterTextSplitter/CharacterTextSplitter.ts new file mode 100644 index 00000000..90387e8b --- /dev/null +++ b/packages/components/nodes/textsplitters/CharacterTextSplitter/CharacterTextSplitter.ts @@ -0,0 +1,63 @@ +import { INode, INodeData, INodeParams } from '../../../src/Interface' +import { getBaseClasses } from '../../../src/utils' +import { CharacterTextSplitter, CharacterTextSplitterParams } from 'langchain/text_splitter' + +class CharacterTextSplitter_TextSplitters implements INode { + label: string + name: string + description: string + type: string + icon: string + category: string + baseClasses: string[] + inputs: INodeParams[] + + constructor() { + this.label = 'Character Text Splitter' + this.name = 'characterTextSplitter' + this.type = 'CharacterTextSplitter' + this.icon = 'textsplitter.svg' + this.category = 'Text Splitters' + this.description = `splits only on one type of character (defaults to "\\n\\n").` + this.baseClasses = [this.type, ...getBaseClasses(CharacterTextSplitter)] + this.inputs = [ + { + label: 'Separator', + name: 'separator', + type: 'string', + optional: true + }, + { + label: 'Chunk Size', + name: 'chunkSize', + type: 'number', + default: 1000, + optional: true + }, + { + label: 'Chunk Overlap', + name: 'chunkOverlap', + type: 'number', + optional: true + } + ] + } + + async init(nodeData: INodeData): Promise { + const separator = nodeData.inputs?.separator as string + const chunkSize = nodeData.inputs?.chunkSize as string + const chunkOverlap = nodeData.inputs?.chunkOverlap as string + + const obj = {} as CharacterTextSplitterParams + + if (separator) obj.separator = separator + if (chunkSize) obj.chunkSize = parseInt(chunkSize, 10) + if (chunkOverlap) obj.chunkOverlap = parseInt(chunkOverlap, 10) + + const splitter = new CharacterTextSplitter(obj) + + return splitter + } +} + +module.exports = { nodeClass: CharacterTextSplitter_TextSplitters } diff --git a/packages/components/nodes/textsplitters/CharacterTextSplitter/textsplitter.svg b/packages/components/nodes/textsplitters/CharacterTextSplitter/textsplitter.svg new file mode 100644 index 00000000..73145e2d --- /dev/null +++ b/packages/components/nodes/textsplitters/CharacterTextSplitter/textsplitter.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/packages/components/nodes/textsplitters/MarkdownTextSplitter/MarkdownTextSplitter.ts b/packages/components/nodes/textsplitters/MarkdownTextSplitter/MarkdownTextSplitter.ts new file mode 100644 index 00000000..02c37d8d --- /dev/null +++ b/packages/components/nodes/textsplitters/MarkdownTextSplitter/MarkdownTextSplitter.ts @@ -0,0 +1,55 @@ +import { INode, INodeData, INodeParams } from '../../../src/Interface' +import { getBaseClasses } from '../../../src/utils' +import { MarkdownTextSplitter, MarkdownTextSplitterParams } from 'langchain/text_splitter' + +class MarkdownTextSplitter_TextSplitters implements INode { + label: string + name: string + description: string + type: string + icon: string + category: string + baseClasses: string[] + inputs: INodeParams[] + + constructor() { + this.label = 'Markdown Text Splitter' + this.name = 'markdownTextSplitter' + this.type = 'MarkdownTextSplitter' + this.icon = 'markdownTextSplitter.svg' + this.category = 'Text Splitters' + this.description = `Split your content into documents based on the Markdown headers` + this.baseClasses = [this.type, ...getBaseClasses(MarkdownTextSplitter)] + this.inputs = [ + { + label: 'Chunk Size', + name: 'chunkSize', + type: 'number', + default: 1000, + optional: true + }, + { + label: 'Chunk Overlap', + name: 'chunkOverlap', + type: 'number', + optional: true + } + ] + } + + async init(nodeData: INodeData): Promise { + const chunkSize = nodeData.inputs?.chunkSize as string + const chunkOverlap = nodeData.inputs?.chunkOverlap as string + + const obj = {} as MarkdownTextSplitterParams + + if (chunkSize) obj.chunkSize = parseInt(chunkSize, 10) + if (chunkOverlap) obj.chunkOverlap = parseInt(chunkOverlap, 10) + + const splitter = new MarkdownTextSplitter(obj) + + return splitter + } +} + +module.exports = { nodeClass: MarkdownTextSplitter_TextSplitters } diff --git a/packages/components/nodes/textsplitters/MarkdownTextSplitter/markdownTextSplitter.svg b/packages/components/nodes/textsplitters/MarkdownTextSplitter/markdownTextSplitter.svg new file mode 100644 index 00000000..f7d45d60 --- /dev/null +++ b/packages/components/nodes/textsplitters/MarkdownTextSplitter/markdownTextSplitter.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/components/nodes/textsplitters/RecursiveCharacterTextSplitter/RecursiveCharacterTextSplitter.ts b/packages/components/nodes/textsplitters/RecursiveCharacterTextSplitter/RecursiveCharacterTextSplitter.ts index d74b2903..432b5ca9 100644 --- a/packages/components/nodes/textsplitters/RecursiveCharacterTextSplitter/RecursiveCharacterTextSplitter.ts +++ b/packages/components/nodes/textsplitters/RecursiveCharacterTextSplitter/RecursiveCharacterTextSplitter.ts @@ -18,7 +18,7 @@ class RecursiveCharacterTextSplitter_TextSplitters implements INode { this.type = 'RecursiveCharacterTextSplitter' this.icon = 'textsplitter.svg' this.category = 'Text Splitters' - this.description = `Split documents recursively by different characters - starting with "\n\n", then "\n", then " "` + this.description = `Split documents recursively by different characters - starting with "\\n\\n", then "\\n", then " "` this.baseClasses = [this.type, ...getBaseClasses(RecursiveCharacterTextSplitter)] this.inputs = [ { diff --git a/packages/components/nodes/textsplitters/TokenTextSplitter/TokenTextSplitter.ts b/packages/components/nodes/textsplitters/TokenTextSplitter/TokenTextSplitter.ts new file mode 100644 index 00000000..8c8d6abe --- /dev/null +++ b/packages/components/nodes/textsplitters/TokenTextSplitter/TokenTextSplitter.ts @@ -0,0 +1,86 @@ +import { INode, INodeData, INodeParams } from '../../../src/Interface' +import { getBaseClasses } from '../../../src/utils' +import { TokenTextSplitter, TokenTextSplitterParams } from 'langchain/text_splitter' +import { TiktokenEncoding } from '@dqbd/tiktoken' + +class TokenTextSplitter_TextSplitters implements INode { + label: string + name: string + description: string + type: string + icon: string + category: string + baseClasses: string[] + inputs: INodeParams[] + + constructor() { + this.label = 'Token Text Splitter' + this.name = 'tokenTextSplitter' + this.type = 'TokenTextSplitter' + this.icon = 'tiktoken.svg' + this.category = 'Text Splitters' + this.description = `Splits a raw text string by first converting the text into BPE tokens, then split these tokens into chunks and convert the tokens within a single chunk back into text.` + this.baseClasses = [this.type, ...getBaseClasses(TokenTextSplitter)] + this.inputs = [ + { + label: 'Encoding Name', + name: 'encodingName', + type: 'options', + options: [ + { + label: 'gpt2', + name: 'gpt2' + }, + { + label: 'r50k_base', + name: 'r50k_base' + }, + { + label: 'p50k_base', + name: 'p50k_base' + }, + { + label: 'p50k_edit', + name: 'p50k_edit' + }, + { + label: 'cl100k_base', + name: 'cl100k_base' + } + ], + default: 'gpt2' + }, + { + label: 'Chunk Size', + name: 'chunkSize', + type: 'number', + default: 1000, + optional: true + }, + { + label: 'Chunk Overlap', + name: 'chunkOverlap', + type: 'number', + optional: true + } + ] + } + + async init(nodeData: INodeData): Promise { + const encodingName = nodeData.inputs?.encodingName as string + const chunkSize = nodeData.inputs?.chunkSize as string + const chunkOverlap = nodeData.inputs?.chunkOverlap as string + + const obj = {} as TokenTextSplitterParams + + obj.encodingName = encodingName as TiktokenEncoding + if (chunkSize) obj.chunkSize = parseInt(chunkSize, 10) + if (chunkOverlap) obj.chunkOverlap = parseInt(chunkOverlap, 10) + + const splitter = new TokenTextSplitter(obj) + + return splitter + } +} + +module.exports = { nodeClass: TokenTextSplitter_TextSplitters } diff --git a/packages/components/nodes/textsplitters/TokenTextSplitter/tiktoken.svg b/packages/components/nodes/textsplitters/TokenTextSplitter/tiktoken.svg new file mode 100644 index 00000000..833cfae1 --- /dev/null +++ b/packages/components/nodes/textsplitters/TokenTextSplitter/tiktoken.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/packages/components/package.json b/packages/components/package.json index 884d02e6..bf739231 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "flowise-components", - "version": "1.2.4", + "version": "1.2.5", "description": "Flowiseai Components", "main": "dist/src/index", "types": "dist/src/index.d.ts", @@ -16,7 +16,7 @@ }, "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@dqbd/tiktoken": "^1.0.4", + "@dqbd/tiktoken": "^1.0.7", "@huggingface/inference": "^1.6.3", "@pinecone-database/pinecone": "^0.0.12", "@supabase/supabase-js": "^2.21.0", @@ -29,7 +29,7 @@ "express": "^4.17.3", "form-data": "^4.0.0", "graphql": "^16.6.0", - "langchain": "^0.0.66", + "langchain": "^0.0.73", "mammoth": "^1.5.1", "moment": "^2.29.3", "node-fetch": "2", diff --git a/packages/server/package.json b/packages/server/package.json index 785b0205..c30ac8c1 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "flowise", - "version": "1.2.3", + "version": "1.2.4", "description": "Flowiseai Server", "main": "dist/index", "types": "dist/index.d.ts", diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index 68c30172..a168570d 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -368,7 +368,11 @@ export class App { if ( Object.prototype.hasOwnProperty.call(this.chatflowPool.activeChatflows, chatflowid) && this.chatflowPool.activeChatflows[chatflowid].inSync && - isSameOverrideConfig(this.chatflowPool.activeChatflows[chatflowid].overrideConfig, incomingInput.overrideConfig) && + isSameOverrideConfig( + isInternal, + this.chatflowPool.activeChatflows[chatflowid].overrideConfig, + incomingInput.overrideConfig + ) && !isStartNodeDependOnInput(this.chatflowPool.activeChatflows[chatflowid].startingNodes) ) { nodeToExecuteData = this.chatflowPool.activeChatflows[chatflowid].endingNodeData diff --git a/packages/server/src/utils/index.ts b/packages/server/src/utils/index.ts index 80c017e1..1b4b41c6 100644 --- a/packages/server/src/utils/index.ts +++ b/packages/server/src/utils/index.ts @@ -388,11 +388,17 @@ export const isStartNodeDependOnInput = (startingNodes: IReactFlowNode[]): boole /** * Rebuild flow if new override config is provided + * @param {boolean} isInternal * @param {ICommonObject} existingOverrideConfig * @param {ICommonObject} newOverrideConfig * @returns {boolean} */ -export const isSameOverrideConfig = (existingOverrideConfig?: ICommonObject, newOverrideConfig?: ICommonObject): boolean => { +export const isSameOverrideConfig = ( + isInternal: boolean, + existingOverrideConfig?: ICommonObject, + newOverrideConfig?: ICommonObject +): boolean => { + if (isInternal) return true if ( existingOverrideConfig && Object.keys(existingOverrideConfig).length && diff --git a/packages/ui/package.json b/packages/ui/package.json index a2558fe1..1e22bca3 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "flowise-ui", - "version": "1.2.2", + "version": "1.2.3", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://flowiseai.com", "author": { diff --git a/packages/ui/src/views/canvas/CanvasHeader.js b/packages/ui/src/views/canvas/CanvasHeader.js index 70c6aa02..3a4abb79 100644 --- a/packages/ui/src/views/canvas/CanvasHeader.js +++ b/packages/ui/src/views/canvas/CanvasHeader.js @@ -89,7 +89,7 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl } const onSaveChatflowClick = () => { - if (chatflow.id) handleSaveFlow(chatflow.name) + if (chatflow.id) handleSaveFlow(flowName) else setFlowDialogOpen(true) }