From fa4d8b66437187c9ce59be882db7443e58889061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C5=9F=C4=B1k?= <41375111+isikhi@users.noreply.github.com> Date: Mon, 28 Aug 2023 02:50:37 +0300 Subject: [PATCH 1/8] fix: unknown error throwing on missing credentials. error handling/message humanized --- packages/components/src/utils.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/components/src/utils.ts b/packages/components/src/utils.ts index 8d06a650..91374bb4 100644 --- a/packages/components/src/utils.ts +++ b/packages/components/src/utils.ts @@ -432,6 +432,10 @@ export const getCredentialData = async (selectedCredentialId: string, options: I const databaseEntities = options.databaseEntities as IDatabaseEntity try { + if (!selectedCredentialId) { + return {} + } + const credential = await appDataSource.getRepository(databaseEntities['Credential']).findOneBy({ id: selectedCredentialId }) From a4f9b75d048296744f44325c19137d2b5abcc0c9 Mon Sep 17 00:00:00 2001 From: Henry Date: Wed, 30 Aug 2023 11:37:28 +0100 Subject: [PATCH 2/8] update autogpt --- .../nodes/agents/AutoGPT/AutoGPT.ts | 103 +++++++++++++++++- packages/server/src/utils/index.ts | 2 +- 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/packages/components/nodes/agents/AutoGPT/AutoGPT.ts b/packages/components/nodes/agents/AutoGPT/AutoGPT.ts index 69e9b9ed..6c26b944 100644 --- a/packages/components/nodes/agents/AutoGPT/AutoGPT.ts +++ b/packages/components/nodes/agents/AutoGPT/AutoGPT.ts @@ -2,8 +2,15 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface' import { BaseChatModel } from 'langchain/chat_models/base' import { AutoGPT } from 'langchain/experimental/autogpt' import { Tool } from 'langchain/tools' +import { AIMessage, HumanMessage, SystemMessage } from 'langchain/schema' import { VectorStoreRetriever } from 'langchain/vectorstores/base' import { flatten } from 'lodash' +import { StructuredTool } from 'langchain/tools' +import { LLMChain } from 'langchain/chains' +import { PromptTemplate } from 'langchain/prompts' + +type ObjectTool = StructuredTool +const FINISH_NAME = 'finish' class AutoGPT_Agents implements INode { label: string @@ -88,13 +95,107 @@ class AutoGPT_Agents implements INode { async run(nodeData: INodeData, input: string): Promise { const executor = nodeData.instance as AutoGPT + const model = nodeData.inputs?.model as BaseChatModel + try { + let totalAssistantReply = '' + executor.run = async (goals: string[]): Promise => { + const user_input = 'Determine which next command to use, and respond using the format specified above:' + let loopCount = 0 + while (loopCount < executor.maxIterations) { + loopCount += 1 + + const { text: assistantReply } = await executor.chain.call({ + goals, + user_input, + memory: executor.memory, + messages: executor.fullMessageHistory + }) + + // eslint-disable-next-line no-console + console.log('\x1b[92m\x1b[1m\n*****AutoGPT*****\n\x1b[0m\x1b[0m') + // eslint-disable-next-line no-console + console.log(assistantReply) + totalAssistantReply += assistantReply + '\n' + executor.fullMessageHistory.push(new HumanMessage(user_input)) + executor.fullMessageHistory.push(new AIMessage(assistantReply)) + + const action = await executor.outputParser.parse(assistantReply) + const tools = executor.tools.reduce((acc, tool) => ({ ...acc, [tool.name]: tool }), {} as { [key: string]: ObjectTool }) + if (action.name === FINISH_NAME) { + return action.args.response + } + let result: string + if (action.name in tools) { + const tool = tools[action.name] + let observation + try { + observation = await tool.call(action.args) + } catch (e) { + observation = `Error in args: ${e}` + } + result = `Command ${tool.name} returned: ${observation}` + } else if (action.name === 'ERROR') { + result = `Error: ${action.args}. ` + } else { + result = `Unknown command '${action.name}'. Please refer to the 'COMMANDS' list for available commands and only respond in the specified JSON format.` + } + + let memoryToAdd = `Assistant Reply: ${assistantReply}\nResult: ${result} ` + if (executor.feedbackTool) { + const feedback = `\n${await executor.feedbackTool.call('Input: ')}` + if (feedback === 'q' || feedback === 'stop') { + return 'EXITING' + } + memoryToAdd += feedback + } + + const documents = await executor.textSplitter.createDocuments([memoryToAdd]) + await executor.memory.addDocuments(documents) + executor.fullMessageHistory.push(new SystemMessage(result)) + } + + return undefined + } + const res = await executor.run([input]) - return res || 'I have completed all my tasks.' + + if (!res) { + const sentence = `Unfortunately I was not able to complete all the task. Here is the chain of thoughts:` + return `${await rephraseString(sentence, model)}\n\`\`\`javascript\n${totalAssistantReply}\n\`\`\`\n` + } + + const sentence = `I have completed all my tasks. Here is the chain of thoughts:` + let writeFilePath = '' + const writeTool = executor.tools.find((tool) => tool.name === 'write_file') + if (executor.tools.length && writeTool) { + writeFilePath = (writeTool as any).store.basePath + } + return `${await rephraseString( + sentence, + model + )}\n\`\`\`javascript\n${totalAssistantReply}\n\`\`\`\nAnd the final result:\n\`\`\`javascript\n${res}\n\`\`\`\n${ + writeFilePath + ? await rephraseString( + `You can download the final result displayed above, or see if a new file has been successfully written to \`${writeFilePath}\``, + model + ) + : '' + }` } catch (e) { throw new Error(e) } } } +const rephraseString = async (sentence: string, model: BaseChatModel) => { + const promptTemplate = new PromptTemplate({ + template: 'You are a helpful Assistant that rephrase a sentence: {sentence}', + inputVariables: ['sentence'] + }) + const chain = new LLMChain({ llm: model, prompt: promptTemplate }) + const res = await chain.call({ sentence }) + return res?.text +} + module.exports = { nodeClass: AutoGPT_Agents } diff --git a/packages/server/src/utils/index.ts b/packages/server/src/utils/index.ts index 9be26987..b95dd301 100644 --- a/packages/server/src/utils/index.ts +++ b/packages/server/src/utils/index.ts @@ -481,7 +481,7 @@ export const isStartNodeDependOnInput = (startingNodes: IReactFlowNode[], nodes: if (inputVariables.length > 0) return true } } - const whitelistNodeNames = ['vectorStoreToDocument'] + const whitelistNodeNames = ['vectorStoreToDocument', 'autoGPT'] for (const node of nodes) { if (whitelistNodeNames.includes(node.data.name)) return true } From 16684192bc50a542afc2b99ad23048c411f499b9 Mon Sep 17 00:00:00 2001 From: Henry Date: Wed, 30 Aug 2023 11:49:13 +0100 Subject: [PATCH 3/8] update custom chat open ai --- .../ChatOpenAICustom.ts} | 15 ++++++++------- .../openai.png | Bin 2 files changed, 8 insertions(+), 7 deletions(-) rename packages/components/nodes/chatmodels/{ChatOpenAIFineTuned/ChatOpenAIFineTuned.ts => ChatOpenAICustom/ChatOpenAICustom.ts} (92%) rename packages/components/nodes/chatmodels/{ChatOpenAIFineTuned => ChatOpenAICustom}/openai.png (100%) diff --git a/packages/components/nodes/chatmodels/ChatOpenAIFineTuned/ChatOpenAIFineTuned.ts b/packages/components/nodes/chatmodels/ChatOpenAICustom/ChatOpenAICustom.ts similarity index 92% rename from packages/components/nodes/chatmodels/ChatOpenAIFineTuned/ChatOpenAIFineTuned.ts rename to packages/components/nodes/chatmodels/ChatOpenAICustom/ChatOpenAICustom.ts index bfe3ba7a..29c1181a 100644 --- a/packages/components/nodes/chatmodels/ChatOpenAIFineTuned/ChatOpenAIFineTuned.ts +++ b/packages/components/nodes/chatmodels/ChatOpenAICustom/ChatOpenAICustom.ts @@ -2,7 +2,7 @@ import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Inter import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils' import { ChatOpenAI, OpenAIChatInput } from 'langchain/chat_models/openai' -class ChatOpenAIFineTuned_ChatModels implements INode { +class ChatOpenAICustom_ChatModels implements INode { label: string name: string version: number @@ -15,19 +15,20 @@ class ChatOpenAIFineTuned_ChatModels implements INode { inputs: INodeParams[] constructor() { - this.label = 'ChatOpenAI Fine-Tuned' - this.name = 'chatOpenAIFineTuned' + this.label = 'ChatOpenAI Custom' + this.name = 'chatOpenAICustom' this.version = 1.0 - this.type = 'ChatOpenAI-FineTuned' + this.type = 'ChatOpenAI-Custom' this.icon = 'openai.png' this.category = 'Chat Models' - this.description = 'Wrapper around fine-tuned OpenAI LLM that use the Chat endpoint' + this.description = 'Custom/FineTuned model using OpenAI Chat compatible API' this.baseClasses = [this.type, ...getBaseClasses(ChatOpenAI)] this.credential = { label: 'Connect Credential', name: 'credential', type: 'credential', - credentialNames: ['openAIApi'] + credentialNames: ['openAIApi'], + optional: true } this.inputs = [ { @@ -146,4 +147,4 @@ class ChatOpenAIFineTuned_ChatModels implements INode { } } -module.exports = { nodeClass: ChatOpenAIFineTuned_ChatModels } +module.exports = { nodeClass: ChatOpenAICustom_ChatModels } diff --git a/packages/components/nodes/chatmodels/ChatOpenAIFineTuned/openai.png b/packages/components/nodes/chatmodels/ChatOpenAICustom/openai.png similarity index 100% rename from packages/components/nodes/chatmodels/ChatOpenAIFineTuned/openai.png rename to packages/components/nodes/chatmodels/ChatOpenAICustom/openai.png From fda49637ce592f80f2b990a1579637bea1531612 Mon Sep 17 00:00:00 2001 From: Henry Date: Wed, 30 Aug 2023 12:28:01 +0100 Subject: [PATCH 4/8] add additional params --- .../nodes/documentloaders/Github/Github.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/packages/components/nodes/documentloaders/Github/Github.ts b/packages/components/nodes/documentloaders/Github/Github.ts index 079bffb0..b49569da 100644 --- a/packages/components/nodes/documentloaders/Github/Github.ts +++ b/packages/components/nodes/documentloaders/Github/Github.ts @@ -51,6 +51,32 @@ class Github_DocumentLoaders implements INode { type: 'boolean', optional: true }, + { + label: 'Max Concurrency', + name: 'maxConcurrency', + type: 'number', + optional: true, + additionalParams: true + }, + { + label: 'Ignore Paths', + name: 'ignorePath', + description: 'An array of paths to be ignored', + placeholder: `["*.md"]`, + type: 'string', + rows: 4, + optional: true, + additionalParams: true + }, + { + label: 'Max Retries', + name: 'maxRetries', + description: + 'The maximum number of retries that can be made for a single call, with an exponential backoff between each attempt. Defaults to 2.', + type: 'number', + optional: true, + additionalParams: true + }, { label: 'Text Splitter', name: 'textSplitter', @@ -73,6 +99,9 @@ class Github_DocumentLoaders implements INode { const recursive = nodeData.inputs?.recursive as boolean const textSplitter = nodeData.inputs?.textSplitter as TextSplitter const metadata = nodeData.inputs?.metadata + const maxConcurrency = nodeData.inputs?.maxConcurrency as string + const maxRetries = nodeData.inputs?.maxRetries as string + const ignorePath = nodeData.inputs?.ignorePath as string const credentialData = await getCredentialData(nodeData.credential ?? '', options) const accessToken = getCredentialParam('accessToken', credentialData, nodeData) @@ -84,6 +113,9 @@ class Github_DocumentLoaders implements INode { } if (accessToken) githubOptions.accessToken = accessToken + if (maxConcurrency) githubOptions.maxConcurrency = parseInt(maxConcurrency, 10) + if (maxRetries) githubOptions.maxRetries = parseInt(maxRetries, 10) + if (ignorePath) githubOptions.ignorePaths = JSON.parse(ignorePath) const loader = new GithubRepoLoader(repoLink, githubOptions) const docs = textSplitter ? await loader.loadAndSplit(textSplitter) : await loader.load() From b2627cafa38334e1188d9ea82fee6d35ee8114a0 Mon Sep 17 00:00:00 2001 From: Henry Date: Wed, 30 Aug 2023 12:29:32 +0100 Subject: [PATCH 5/8] update steps --- packages/components/nodes/documentloaders/Github/Github.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/components/nodes/documentloaders/Github/Github.ts b/packages/components/nodes/documentloaders/Github/Github.ts index b49569da..095b3e76 100644 --- a/packages/components/nodes/documentloaders/Github/Github.ts +++ b/packages/components/nodes/documentloaders/Github/Github.ts @@ -55,6 +55,7 @@ class Github_DocumentLoaders implements INode { label: 'Max Concurrency', name: 'maxConcurrency', type: 'number', + step: 1, optional: true, additionalParams: true }, @@ -74,6 +75,7 @@ class Github_DocumentLoaders implements INode { description: 'The maximum number of retries that can be made for a single call, with an exponential backoff between each attempt. Defaults to 2.', type: 'number', + step: 1, optional: true, additionalParams: true }, From 6372cb9c72c784021af78c79f57b42ee39e4b29a Mon Sep 17 00:00:00 2001 From: Henry Date: Wed, 30 Aug 2023 12:34:50 +0100 Subject: [PATCH 6/8] update marketplace --- .../nodes/documentloaders/Github/Github.ts | 2 +- .../chatflows/Flowise Docs QnA.json | 31 ++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/packages/components/nodes/documentloaders/Github/Github.ts b/packages/components/nodes/documentloaders/Github/Github.ts index 095b3e76..6495e8e9 100644 --- a/packages/components/nodes/documentloaders/Github/Github.ts +++ b/packages/components/nodes/documentloaders/Github/Github.ts @@ -18,7 +18,7 @@ class Github_DocumentLoaders implements INode { constructor() { this.label = 'Github' this.name = 'github' - this.version = 1.0 + this.version = 2.0 this.type = 'Document' this.icon = 'github.png' this.category = 'Document Loaders' diff --git a/packages/server/marketplaces/chatflows/Flowise Docs QnA.json b/packages/server/marketplaces/chatflows/Flowise Docs QnA.json index 6d11f3d2..f8b274a1 100644 --- a/packages/server/marketplaces/chatflows/Flowise Docs QnA.json +++ b/packages/server/marketplaces/chatflows/Flowise Docs QnA.json @@ -265,7 +265,7 @@ "id": "github_0", "label": "Github", "name": "github", - "version": 1, + "version": 2, "type": "Document", "baseClasses": ["Document"], "category": "Document Loaders", @@ -301,6 +301,35 @@ "optional": true, "id": "github_0-input-recursive-boolean" }, + { + "label": "Max Concurrency", + "name": "maxConcurrency", + "type": "number", + "step": 1, + "optional": true, + "additionalParams": true, + "id": "github_0-input-maxConcurrency-number" + }, + { + "label": "Ignore Paths", + "name": "ignorePath", + "type": "string", + "description": "An array of paths to be ignored", + "placeholder": "[\"*.md\"]", + "rows": 4, + "optional": true, + "additionalParams": true, + "id": "github_0-input-ignorePath-string" + }, + { + "label": "Max Retries", + "name": "maxRetries", + "description": "The maximum number of retries that can be made for a single call, with an exponential backoff between each attempt. Defaults to 2.", + "type": "number", + "optional": true, + "additionalParams": true, + "id": "github_0-input-maxRetries-number" + }, { "label": "Metadata", "name": "metadata", From d03108d0ac1b53179bf46794edf1499973f2ff2d Mon Sep 17 00:00:00 2001 From: Yavisht Katgara Date: Fri, 1 Sep 2023 11:46:37 +1000 Subject: [PATCH 7/8] feat: dateTime marketplace tool --- .../server/marketplaces/tools/Get Current DateTime.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 packages/server/marketplaces/tools/Get Current DateTime.json diff --git a/packages/server/marketplaces/tools/Get Current DateTime.json b/packages/server/marketplaces/tools/Get Current DateTime.json new file mode 100644 index 00000000..b6860b30 --- /dev/null +++ b/packages/server/marketplaces/tools/Get Current DateTime.json @@ -0,0 +1,8 @@ +{ + "name": "todays_date_time", + "description": "Useful to get todays day, date and time.", + "color": "linear-gradient(rgb(117,118,129), rgb(230,10,250))", + "iconSrc": "https://raw.githubusercontent.com/gilbarbara/logos/main/logos/javascript.svg", + "schema": "[]", + "func": "const timeZone = 'Australia/Sydney';\nconst options = {\n timeZone: timeZone,\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n weekday: 'long',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: true\n};\nconst today = new Date();\nconst formattedDate = today.toLocaleString('en-GB', options);\nconst result = {\n \"formattedDate\": formattedDate,\n \"timezone\": timeZone\n};\nreturn JSON.stringify(result);\n" +} From 8f83bb670093ebe4befda15905f8426969da0d3a Mon Sep 17 00:00:00 2001 From: Henry Date: Fri, 1 Sep 2023 10:59:38 +0100 Subject: [PATCH 8/8] removed CLA from contributing md --- CONTRIBUTING.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 90ba5498..05925b1e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -156,10 +156,6 @@ npx flowise start --PORT=3000 --DEBUG=true A member of the FlowiseAI team will automatically be notified/assigned when you open a pull request. You can also reach out to us on [Discord](https://discord.gg/jbaHfsRVBW). -## 📃 Contributor License Agreement - -Before we can merge your contribution you have to sign our [Contributor License Agreement (CLA)](https://cla-assistant.io/FlowiseAI/Flowise). The CLA contains the terms and conditions under which the contribution is submitted. You need to do this only once for your first pull request. Keep in mind that without a signed CLA we cannot merge your contribution. - ## 📜 Code of Conduct This project and everyone participating in it are governed by the Code of Conduct which can be found in the [file](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to hello@flowiseai.com.