Merge branch 'main' into feature/OpenAI-Function

# Conflicts:
#	packages/server/marketplaces/chatflows/API Agent OpenAI.json
#	packages/server/marketplaces/chatflows/Conversational Retrieval Agent.json
#	packages/server/marketplaces/chatflows/OpenAI Agent.json
This commit is contained in:
Henry
2023-11-29 00:26:36 +00:00
43 changed files with 554 additions and 723 deletions
@@ -3,7 +3,7 @@
"nodes": [
{
"width": 300,
"height": 510,
"height": 491,
"id": "openApiChain_1",
"position": {
"x": 1203.1825726424859,
@@ -13,8 +13,8 @@
"data": {
"id": "openApiChain_1",
"label": "OpenAPI Chain",
"name": "openApiChain",
"version": 1,
"name": "openApiChain",
"type": "OpenAPIChain",
"baseClasses": ["OpenAPIChain", "BaseChain"],
"category": "Chains",
@@ -78,7 +78,7 @@
},
{
"width": 300,
"height": 523,
"height": 574,
"id": "chatOpenAI_1",
"position": {
"x": 792.3201947594027,
@@ -88,8 +88,8 @@
"data": {
"id": "chatOpenAI_1",
"label": "ChatOpenAI",
"name": "chatOpenAI",
"version": 2,
"name": "chatOpenAI",
"type": "ChatOpenAI",
"baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel"],
"category": "Chat Models",
@@ -259,8 +259,8 @@
"data": {
"id": "chainTool_0",
"label": "Chain Tool",
"name": "chainTool",
"version": 1,
"name": "chainTool",
"type": "ChainTool",
"baseClasses": ["ChainTool", "DynamicTool", "Tool", "StructuredTool"],
"category": "Tools",
@@ -397,7 +397,7 @@
},
{
"width": 300,
"height": 523,
"height": 574,
"id": "chatOpenAI_2",
"position": {
"x": 1645.450699499575,
@@ -407,8 +407,8 @@
"data": {
"id": "chatOpenAI_2",
"label": "ChatOpenAI",
"name": "chatOpenAI",
"version": 2,
"name": "chatOpenAI",
"type": "ChatOpenAI",
"baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel"],
"category": "Chat Models",
@@ -578,8 +578,8 @@
"data": {
"id": "bufferMemory_0",
"label": "Buffer Memory",
"name": "bufferMemory",
"version": 1,
"name": "bufferMemory",
"type": "BufferMemory",
"baseClasses": ["BufferMemory", "BaseChatMemory", "BaseMemory"],
"category": "Memory",
@@ -657,17 +657,6 @@
"label": ""
}
},
{
"source": "chatOpenAI_2",
"sourceHandle": "chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel",
"target": "openAIFunctionAgent_0",
"targetHandle": "openAIFunctionAgent_0-input-model-BaseChatModel",
"type": "buttonedge",
"id": "chatOpenAI_2-chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-openAIFunctionAgent_0-openAIFunctionAgent_0-input-model-BaseChatModel",
"data": {
"label": ""
}
},
{
"source": "bufferMemory_0",
"sourceHandle": "bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory",
@@ -678,6 +667,17 @@
"data": {
"label": ""
}
},
{
"source": "chatOpenAI_2",
"sourceHandle": "chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel",
"target": "openAIFunctionAgent_0",
"targetHandle": "openAIFunctionAgent_0-input-model-ChatOpenAI | AzureChatOpenAI",
"type": "buttonedge",
"id": "chatOpenAI_2-chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-openAIFunctionAgent_0-openAIFunctionAgent_0-input-model-ChatOpenAI | AzureChatOpenAI",
"data": {
"label": ""
}
}
]
}
@@ -13,8 +13,8 @@
"data": {
"id": "getApiChain_0",
"label": "GET API Chain",
"name": "getApiChain",
"version": 1,
"name": "getApiChain",
"type": "GETApiChain",
"baseClasses": ["GETApiChain", "BaseChain", "BaseLangChain"],
"category": "Chains",
@@ -102,8 +102,8 @@
"data": {
"id": "chainTool_0",
"label": "Chain Tool",
"name": "chainTool",
"version": 1,
"name": "chainTool",
"type": "ChainTool",
"baseClasses": ["ChainTool", "DynamicTool", "Tool", "StructuredTool", "BaseLangChain"],
"category": "Tools",
@@ -176,8 +176,8 @@
"data": {
"id": "bufferMemory_0",
"label": "Buffer Memory",
"name": "bufferMemory",
"version": 1,
"name": "bufferMemory",
"type": "BufferMemory",
"baseClasses": ["BufferMemory", "BaseChatMemory", "BaseMemory"],
"category": "Memory",
@@ -233,8 +233,8 @@
"data": {
"id": "chainTool_1",
"label": "Chain Tool",
"name": "chainTool",
"version": 1,
"name": "chainTool",
"type": "ChainTool",
"baseClasses": ["ChainTool", "DynamicTool", "Tool", "StructuredTool", "BaseLangChain"],
"category": "Tools",
@@ -307,8 +307,8 @@
"data": {
"id": "postApiChain_0",
"label": "POST API Chain",
"name": "postApiChain",
"version": 1,
"name": "postApiChain",
"type": "POSTApiChain",
"baseClasses": ["POSTApiChain", "BaseChain", "BaseLangChain"],
"category": "Chains",
@@ -386,7 +386,7 @@
},
{
"width": 300,
"height": 523,
"height": 574,
"id": "chatOpenAI_2",
"position": {
"x": 572.8941615312035,
@@ -396,8 +396,8 @@
"data": {
"id": "chatOpenAI_2",
"label": "ChatOpenAI",
"name": "chatOpenAI",
"version": 2,
"name": "chatOpenAI",
"type": "ChatOpenAI",
"baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel"],
"category": "Chat Models",
@@ -557,7 +557,7 @@
},
{
"width": 300,
"height": 523,
"height": 574,
"id": "chatOpenAI_1",
"position": {
"x": 828.7788305309582,
@@ -567,8 +567,8 @@
"data": {
"id": "chatOpenAI_1",
"label": "ChatOpenAI",
"name": "chatOpenAI",
"version": 2,
"name": "chatOpenAI",
"type": "ChatOpenAI",
"baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel"],
"category": "Chat Models",
@@ -728,7 +728,7 @@
},
{
"width": 300,
"height": 523,
"height": 574,
"id": "chatOpenAI_3",
"position": {
"x": 1148.338912314111,
@@ -738,8 +738,8 @@
"data": {
"id": "chatOpenAI_3",
"label": "ChatOpenAI",
"name": "chatOpenAI",
"version": 2,
"name": "chatOpenAI",
"type": "ChatOpenAI",
"baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel"],
"category": "Chat Models",
@@ -869,7 +869,7 @@
}
],
"inputs": {
"modelName": "gpt-3.5-turbo",
"modelName": "gpt-3.5-turbo-16k",
"temperature": 0.9,
"maxTokens": "",
"topP": "",
@@ -902,17 +902,17 @@
"height": 383,
"id": "conversationalAgent_0",
"position": {
"x": 2114.071431691489,
"y": 941.7926368551367
"x": 2090.570467632979,
"y": 969.5131357270544
},
"type": "customNode",
"data": {
"id": "conversationalAgent_0",
"label": "Conversational Agent",
"version": 2,
"name": "conversationalAgent",
"version": 1,
"type": "AgentExecutor",
"baseClasses": ["AgentExecutor", "BaseChain"],
"baseClasses": ["AgentExecutor", "BaseChain", "Runnable"],
"category": "Agents",
"description": "Conversational agent for a chat model. It will utilize chat specific prompts",
"inputParams": [
@@ -938,8 +938,8 @@
{
"label": "Language Model",
"name": "model",
"type": "BaseLanguageModel",
"id": "conversationalAgent_0-input-model-BaseLanguageModel"
"type": "BaseChatModel",
"id": "conversationalAgent_0-input-model-BaseChatModel"
},
{
"label": "Memory",
@@ -956,21 +956,21 @@
},
"outputAnchors": [
{
"id": "conversationalAgent_0-output-conversationalAgent-AgentExecutor|BaseChain",
"id": "conversationalAgent_0-output-conversationalAgent-AgentExecutor|BaseChain|Runnable",
"name": "conversationalAgent",
"label": "AgentExecutor",
"type": "AgentExecutor | BaseChain"
"type": "AgentExecutor | BaseChain | Runnable"
}
],
"outputs": {},
"selected": false
},
"selected": false,
"dragging": false,
"positionAbsolute": {
"x": 2114.071431691489,
"y": 941.7926368551367
}
"x": 2090.570467632979,
"y": 969.5131357270544
},
"dragging": false
}
],
"edges": [
@@ -1044,9 +1044,9 @@
"source": "chatOpenAI_3",
"sourceHandle": "chatOpenAI_3-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel",
"target": "conversationalAgent_0",
"targetHandle": "conversationalAgent_0-input-model-BaseLanguageModel",
"targetHandle": "conversationalAgent_0-input-model-BaseChatModel",
"type": "buttonedge",
"id": "chatOpenAI_3-chatOpenAI_3-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-conversationalAgent_0-conversationalAgent_0-input-model-BaseLanguageModel",
"id": "chatOpenAI_3-chatOpenAI_3-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-conversationalAgent_0-conversationalAgent_0-input-model-BaseChatModel",
"data": {
"label": ""
}
@@ -13,8 +13,8 @@
"data": {
"id": "calculator_1",
"label": "Calculator",
"name": "calculator",
"version": 1,
"name": "calculator",
"type": "Calculator",
"baseClasses": ["Calculator", "Tool", "StructuredTool", "BaseLangChain"],
"category": "Tools",
@@ -52,8 +52,8 @@
"data": {
"id": "bufferMemory_1",
"label": "Buffer Memory",
"name": "bufferMemory",
"version": 1,
"name": "bufferMemory",
"type": "BufferMemory",
"baseClasses": ["BufferMemory", "BaseChatMemory", "BaseMemory"],
"category": "Memory",
@@ -109,8 +109,8 @@
"data": {
"id": "serpAPI_0",
"label": "Serp API",
"name": "serpAPI",
"version": 1,
"name": "serpAPI",
"type": "SerpAPI",
"baseClasses": ["SerpAPI", "Tool", "StructuredTool"],
"category": "Tools",
@@ -146,7 +146,7 @@
},
{
"width": 300,
"height": 523,
"height": 574,
"id": "chatOpenAI_0",
"position": {
"x": 97.01321406237057,
@@ -156,8 +156,8 @@
"data": {
"id": "chatOpenAI_0",
"label": "ChatOpenAI",
"name": "chatOpenAI",
"version": 2,
"name": "chatOpenAI",
"type": "ChatOpenAI",
"baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel"],
"category": "Chat Models",
@@ -287,7 +287,7 @@
}
],
"inputs": {
"modelName": "gpt-3.5-turbo",
"modelName": "gpt-3.5-turbo-16k",
"temperature": 0.9,
"maxTokens": "",
"topP": "",
@@ -320,17 +320,17 @@
"height": 383,
"id": "conversationalAgent_0",
"position": {
"x": 1164.4550359451973,
"y": 283.40041124403075
"x": 1191.1524476753796,
"y": 324.2479396683294
},
"type": "customNode",
"data": {
"id": "conversationalAgent_0",
"label": "Conversational Agent",
"version": 2,
"name": "conversationalAgent",
"version": 1,
"type": "AgentExecutor",
"baseClasses": ["AgentExecutor", "BaseChain"],
"baseClasses": ["AgentExecutor", "BaseChain", "Runnable"],
"category": "Agents",
"description": "Conversational agent for a chat model. It will utilize chat specific prompts",
"inputParams": [
@@ -356,8 +356,8 @@
{
"label": "Language Model",
"name": "model",
"type": "BaseLanguageModel",
"id": "conversationalAgent_0-input-model-BaseLanguageModel"
"type": "BaseChatModel",
"id": "conversationalAgent_0-input-model-BaseChatModel"
},
{
"label": "Memory",
@@ -374,10 +374,10 @@
},
"outputAnchors": [
{
"id": "conversationalAgent_0-output-conversationalAgent-AgentExecutor|BaseChain",
"id": "conversationalAgent_0-output-conversationalAgent-AgentExecutor|BaseChain|Runnable",
"name": "conversationalAgent",
"label": "AgentExecutor",
"type": "AgentExecutor | BaseChain"
"type": "AgentExecutor | BaseChain | Runnable"
}
],
"outputs": {},
@@ -385,8 +385,8 @@
},
"selected": false,
"positionAbsolute": {
"x": 1164.4550359451973,
"y": 283.40041124403075
"x": 1191.1524476753796,
"y": 324.2479396683294
},
"dragging": false
}
@@ -418,9 +418,9 @@
"source": "chatOpenAI_0",
"sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel",
"target": "conversationalAgent_0",
"targetHandle": "conversationalAgent_0-input-model-BaseLanguageModel",
"targetHandle": "conversationalAgent_0-input-model-BaseChatModel",
"type": "buttonedge",
"id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-conversationalAgent_0-conversationalAgent_0-input-model-BaseLanguageModel",
"id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-conversationalAgent_0-conversationalAgent_0-input-model-BaseChatModel",
"data": {
"label": ""
}
@@ -1127,81 +1127,6 @@
},
"dragging": false
},
{
"width": 300,
"height": 383,
"id": "conversationalAgent_0",
"position": {
"x": 2506.011817109287,
"y": -241.58006840004734
},
"type": "customNode",
"data": {
"id": "conversationalAgent_0",
"label": "Conversational Agent",
"version": 1,
"name": "conversationalAgent",
"type": "AgentExecutor",
"baseClasses": ["AgentExecutor", "BaseChain", "Runnable"],
"category": "Agents",
"description": "Conversational agent for a chat model. It will utilize chat specific prompts",
"inputParams": [
{
"label": "System Message",
"name": "systemMessage",
"type": "string",
"rows": 4,
"default": "Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.",
"optional": true,
"additionalParams": true,
"id": "conversationalAgent_0-input-systemMessage-string"
}
],
"inputAnchors": [
{
"label": "Allowed Tools",
"name": "tools",
"type": "Tool",
"list": true,
"id": "conversationalAgent_0-input-tools-Tool"
},
{
"label": "Language Model",
"name": "model",
"type": "BaseLanguageModel",
"id": "conversationalAgent_0-input-model-BaseLanguageModel"
},
{
"label": "Memory",
"name": "memory",
"type": "BaseChatMemory",
"id": "conversationalAgent_0-input-memory-BaseChatMemory"
}
],
"inputs": {
"tools": ["{{chainTool_2.data.instance}}", "{{chainTool_3.data.instance}}"],
"model": "{{chatOpenAI_2.data.instance}}",
"memory": "{{bufferMemory_0.data.instance}}",
"systemMessage": "Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist."
},
"outputAnchors": [
{
"id": "conversationalAgent_0-output-conversationalAgent-AgentExecutor|BaseChain|Runnable",
"name": "conversationalAgent",
"label": "AgentExecutor",
"type": "AgentExecutor | BaseChain | Runnable"
}
],
"outputs": {},
"selected": false
},
"selected": false,
"positionAbsolute": {
"x": 2506.011817109287,
"y": -241.58006840004734
},
"dragging": false
},
{
"width": 300,
"height": 574,
@@ -1602,6 +1527,81 @@
"y": 75.96855802341503
},
"dragging": false
},
{
"width": 300,
"height": 383,
"id": "conversationalAgent_0",
"position": {
"x": 2432.125364763489,
"y": -105.27942167533908
},
"type": "customNode",
"data": {
"id": "conversationalAgent_0",
"label": "Conversational Agent",
"version": 2,
"name": "conversationalAgent",
"type": "AgentExecutor",
"baseClasses": ["AgentExecutor", "BaseChain", "Runnable"],
"category": "Agents",
"description": "Conversational agent for a chat model. It will utilize chat specific prompts",
"inputParams": [
{
"label": "System Message",
"name": "systemMessage",
"type": "string",
"rows": 4,
"default": "Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.",
"optional": true,
"additionalParams": true,
"id": "conversationalAgent_0-input-systemMessage-string"
}
],
"inputAnchors": [
{
"label": "Allowed Tools",
"name": "tools",
"type": "Tool",
"list": true,
"id": "conversationalAgent_0-input-tools-Tool"
},
{
"label": "Language Model",
"name": "model",
"type": "BaseChatModel",
"id": "conversationalAgent_0-input-model-BaseChatModel"
},
{
"label": "Memory",
"name": "memory",
"type": "BaseChatMemory",
"id": "conversationalAgent_0-input-memory-BaseChatMemory"
}
],
"inputs": {
"tools": ["{{chainTool_2.data.instance}}", "{{chainTool_3.data.instance}}"],
"model": "{{chatOpenAI_2.data.instance}}",
"memory": "{{bufferMemory_0.data.instance}}",
"systemMessage": "Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist."
},
"outputAnchors": [
{
"id": "conversationalAgent_0-output-conversationalAgent-AgentExecutor|BaseChain|Runnable",
"name": "conversationalAgent",
"label": "AgentExecutor",
"type": "AgentExecutor | BaseChain | Runnable"
}
],
"outputs": {},
"selected": false
},
"selected": false,
"positionAbsolute": {
"x": 2432.125364763489,
"y": -105.27942167533908
},
"dragging": false
}
],
"edges": [
@@ -1704,6 +1704,28 @@
"label": ""
}
},
{
"source": "plainText_1",
"sourceHandle": "plainText_1-output-document-Document",
"target": "faiss_0",
"targetHandle": "faiss_0-input-document-Document",
"type": "buttonedge",
"id": "plainText_1-plainText_1-output-document-Document-faiss_0-faiss_0-input-document-Document",
"data": {
"label": ""
}
},
{
"source": "recursiveCharacterTextSplitter_0",
"sourceHandle": "recursiveCharacterTextSplitter_0-output-recursiveCharacterTextSplitter-RecursiveCharacterTextSplitter|TextSplitter|BaseDocumentTransformer|Runnable",
"target": "plainText_1",
"targetHandle": "plainText_1-input-textSplitter-TextSplitter",
"type": "buttonedge",
"id": "recursiveCharacterTextSplitter_0-recursiveCharacterTextSplitter_0-output-recursiveCharacterTextSplitter-RecursiveCharacterTextSplitter|TextSplitter|BaseDocumentTransformer|Runnable-plainText_1-plainText_1-input-textSplitter-TextSplitter",
"data": {
"label": ""
}
},
{
"source": "chainTool_2",
"sourceHandle": "chainTool_2-output-chainTool-ChainTool|DynamicTool|Tool|StructuredTool|BaseLangChain",
@@ -1730,9 +1752,9 @@
"source": "chatOpenAI_2",
"sourceHandle": "chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable",
"target": "conversationalAgent_0",
"targetHandle": "conversationalAgent_0-input-model-BaseLanguageModel",
"targetHandle": "conversationalAgent_0-input-model-BaseChatModel",
"type": "buttonedge",
"id": "chatOpenAI_2-chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-conversationalAgent_0-conversationalAgent_0-input-model-BaseLanguageModel",
"id": "chatOpenAI_2-chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-conversationalAgent_0-conversationalAgent_0-input-model-BaseChatModel",
"data": {
"label": ""
}
@@ -1747,28 +1769,6 @@
"data": {
"label": ""
}
},
{
"source": "plainText_1",
"sourceHandle": "plainText_1-output-document-Document",
"target": "faiss_0",
"targetHandle": "faiss_0-input-document-Document",
"type": "buttonedge",
"id": "plainText_1-plainText_1-output-document-Document-faiss_0-faiss_0-input-document-Document",
"data": {
"label": ""
}
},
{
"source": "recursiveCharacterTextSplitter_0",
"sourceHandle": "recursiveCharacterTextSplitter_0-output-recursiveCharacterTextSplitter-RecursiveCharacterTextSplitter|TextSplitter|BaseDocumentTransformer|Runnable",
"target": "plainText_1",
"targetHandle": "plainText_1-input-textSplitter-TextSplitter",
"type": "buttonedge",
"id": "recursiveCharacterTextSplitter_0-recursiveCharacterTextSplitter_0-output-recursiveCharacterTextSplitter-RecursiveCharacterTextSplitter|TextSplitter|BaseDocumentTransformer|Runnable-plainText_1-plainText_1-input-textSplitter-TextSplitter",
"data": {
"label": ""
}
}
]
}
@@ -13,8 +13,8 @@
"data": {
"id": "calculator_0",
"label": "Calculator",
"name": "calculator",
"version": 1,
"name": "calculator",
"type": "Calculator",
"baseClasses": ["Calculator", "Tool", "StructuredTool", "BaseLangChain", "Serializable"],
"category": "Tools",
@@ -52,8 +52,8 @@
"data": {
"id": "bufferMemory_0",
"label": "Buffer Memory",
"name": "bufferMemory",
"version": 1,
"name": "bufferMemory",
"type": "BufferMemory",
"baseClasses": ["BufferMemory", "BaseChatMemory", "BaseMemory"],
"category": "Memory",
@@ -109,8 +109,8 @@
"data": {
"id": "customTool_0",
"label": "Custom Tool",
"name": "customTool",
"version": 1,
"name": "customTool",
"type": "CustomTool",
"baseClasses": ["CustomTool", "Tool", "StructuredTool"],
"category": "Tools",
@@ -158,8 +158,8 @@
"data": {
"id": "serper_0",
"label": "Serper",
"name": "serper",
"version": 1,
"name": "serper",
"type": "Serper",
"baseClasses": ["Serper", "Tool", "StructuredTool"],
"category": "Tools",
@@ -269,7 +269,7 @@
},
{
"width": 300,
"height": 523,
"height": 574,
"id": "chatOpenAI_0",
"position": {
"x": 817.8210275868742,
@@ -279,8 +279,8 @@
"data": {
"id": "chatOpenAI_0",
"label": "ChatOpenAI",
"name": "chatOpenAI",
"version": 2,
"name": "chatOpenAI",
"type": "ChatOpenAI",
"baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel"],
"category": "Chat Models",
@@ -473,17 +473,6 @@
"label": ""
}
},
{
"source": "chatOpenAI_0",
"sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel",
"target": "openAIFunctionAgent_0",
"targetHandle": "openAIFunctionAgent_0-input-model-BaseChatModel",
"type": "buttonedge",
"id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-openAIFunctionAgent_0-openAIFunctionAgent_0-input-model-BaseChatModel",
"data": {
"label": ""
}
},
{
"source": "bufferMemory_0",
"sourceHandle": "bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory",
@@ -494,6 +483,17 @@
"data": {
"label": ""
}
},
{
"source": "chatOpenAI_0",
"sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel",
"target": "openAIFunctionAgent_0",
"targetHandle": "openAIFunctionAgent_0-input-model-ChatOpenAI | AzureChatOpenAI",
"type": "buttonedge",
"id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-openAIFunctionAgent_0-openAIFunctionAgent_0-input-model-ChatOpenAI | AzureChatOpenAI",
"data": {
"label": ""
}
}
]
}
@@ -14,7 +14,7 @@
"data": {
"id": "openAIAssistant_0",
"label": "OpenAI Assistant",
"version": 1,
"version": 2,
"name": "openAIAssistant",
"type": "OpenAIAssistant",
"baseClasses": ["OpenAIAssistant"],
@@ -27,6 +27,15 @@
"type": "asyncOptions",
"loadMethod": "listAssistants",
"id": "openAIAssistant_0-input-selectedAssistant-asyncOptions"
},
{
"label": "Disable File Download",
"name": "disableFileDownload",
"type": "boolean",
"description": "Messages can contain text, images, or files. In some cases, you may want to prevent others from downloading the files. Learn more from OpenAI File Annotation <a target=\"_blank\" href=\"https://platform.openai.com/docs/assistants/how-it-works/managing-threads-and-messages\">docs</a>",
"optional": true,
"additionalParams": true,
"id": "openAIAssistant_0-input-disableFileDownload-boolean"
}
],
"inputAnchors": [
@@ -13,8 +13,8 @@
"data": {
"id": "bufferMemory_0",
"label": "Buffer Memory",
"name": "bufferMemory",
"version": 1,
"name": "bufferMemory",
"type": "BufferMemory",
"baseClasses": ["BufferMemory", "BaseChatMemory", "BaseMemory"],
"category": "Memory",
@@ -70,8 +70,8 @@
"data": {
"id": "webBrowser_0",
"label": "Web Browser",
"name": "webBrowser",
"version": 1,
"name": "webBrowser",
"type": "WebBrowser",
"baseClasses": ["WebBrowser", "Tool", "StructuredTool", "BaseLangChain"],
"category": "Tools",
@@ -115,82 +115,7 @@
},
{
"width": 300,
"height": 383,
"id": "conversationalAgent_0",
"position": {
"x": 1464.513303631911,
"y": 155.73036805253955
},
"type": "customNode",
"data": {
"id": "conversationalAgent_0",
"label": "Conversational Agent",
"name": "conversationalAgent",
"version": 1,
"type": "AgentExecutor",
"baseClasses": ["AgentExecutor", "BaseChain"],
"category": "Agents",
"description": "Conversational agent for a chat model. It will utilize chat specific prompts",
"inputParams": [
{
"label": "System Message",
"name": "systemMessage",
"type": "string",
"rows": 4,
"default": "Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.",
"optional": true,
"additionalParams": true,
"id": "conversationalAgent_0-input-systemMessage-string"
}
],
"inputAnchors": [
{
"label": "Allowed Tools",
"name": "tools",
"type": "Tool",
"list": true,
"id": "conversationalAgent_0-input-tools-Tool"
},
{
"label": "Language Model",
"name": "model",
"type": "BaseLanguageModel",
"id": "conversationalAgent_0-input-model-BaseLanguageModel"
},
{
"label": "Memory",
"name": "memory",
"type": "BaseChatMemory",
"id": "conversationalAgent_0-input-memory-BaseChatMemory"
}
],
"inputs": {
"tools": ["{{webBrowser_0.data.instance}}"],
"model": "{{chatOpenAI_1.data.instance}}",
"memory": "{{bufferMemory_0.data.instance}}",
"systemMessage": "Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist."
},
"outputAnchors": [
{
"id": "conversationalAgent_0-output-conversationalAgent-AgentExecutor|BaseChain",
"name": "conversationalAgent",
"label": "AgentExecutor",
"type": "AgentExecutor | BaseChain"
}
],
"outputs": {},
"selected": false
},
"selected": false,
"positionAbsolute": {
"x": 1464.513303631911,
"y": 155.73036805253955
},
"dragging": false
},
{
"width": 300,
"height": 523,
"height": 574,
"id": "chatOpenAI_0",
"position": {
"x": 734.7477982032904,
@@ -200,8 +125,8 @@
"data": {
"id": "chatOpenAI_0",
"label": "ChatOpenAI",
"name": "chatOpenAI",
"version": 2,
"name": "chatOpenAI",
"type": "ChatOpenAI",
"baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel"],
"category": "Chat Models",
@@ -371,8 +296,8 @@
"data": {
"id": "openAIEmbeddings_0",
"label": "OpenAI Embeddings",
"name": "openAIEmbeddings",
"version": 1,
"name": "openAIEmbeddings",
"type": "OpenAIEmbeddings",
"baseClasses": ["OpenAIEmbeddings", "Embeddings"],
"category": "Embeddings",
@@ -445,7 +370,7 @@
},
{
"width": 300,
"height": 523,
"height": 574,
"id": "chatOpenAI_1",
"position": {
"x": 68.312124033115,
@@ -455,8 +380,8 @@
"data": {
"id": "chatOpenAI_1",
"label": "ChatOpenAI",
"name": "chatOpenAI",
"version": 2,
"name": "chatOpenAI",
"type": "ChatOpenAI",
"baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel"],
"category": "Chat Models",
@@ -586,7 +511,7 @@
}
],
"inputs": {
"modelName": "gpt-3.5-turbo",
"modelName": "gpt-3.5-turbo-16k",
"temperature": 0.9,
"maxTokens": "",
"topP": "",
@@ -613,6 +538,81 @@
"y": -239.65476709991256
},
"dragging": false
},
{
"width": 300,
"height": 383,
"id": "conversationalAgent_0",
"position": {
"x": 1518.944765840293,
"y": 212.2513364217197
},
"type": "customNode",
"data": {
"id": "conversationalAgent_0",
"label": "Conversational Agent",
"version": 2,
"name": "conversationalAgent",
"type": "AgentExecutor",
"baseClasses": ["AgentExecutor", "BaseChain", "Runnable"],
"category": "Agents",
"description": "Conversational agent for a chat model. It will utilize chat specific prompts",
"inputParams": [
{
"label": "System Message",
"name": "systemMessage",
"type": "string",
"rows": 4,
"default": "Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.",
"optional": true,
"additionalParams": true,
"id": "conversationalAgent_0-input-systemMessage-string"
}
],
"inputAnchors": [
{
"label": "Allowed Tools",
"name": "tools",
"type": "Tool",
"list": true,
"id": "conversationalAgent_0-input-tools-Tool"
},
{
"label": "Language Model",
"name": "model",
"type": "BaseChatModel",
"id": "conversationalAgent_0-input-model-BaseChatModel"
},
{
"label": "Memory",
"name": "memory",
"type": "BaseChatMemory",
"id": "conversationalAgent_0-input-memory-BaseChatMemory"
}
],
"inputs": {
"tools": ["{{webBrowser_0.data.instance}}"],
"model": "{{chatOpenAI_1.data.instance}}",
"memory": "{{bufferMemory_0.data.instance}}",
"systemMessage": "Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist."
},
"outputAnchors": [
{
"id": "conversationalAgent_0-output-conversationalAgent-AgentExecutor|BaseChain|Runnable",
"name": "conversationalAgent",
"label": "AgentExecutor",
"type": "AgentExecutor | BaseChain | Runnable"
}
],
"outputs": {},
"selected": false
},
"selected": false,
"positionAbsolute": {
"x": 1518.944765840293,
"y": 212.2513364217197
},
"dragging": false
}
],
"edges": [
@@ -638,17 +638,6 @@
"label": ""
}
},
{
"source": "chatOpenAI_1",
"sourceHandle": "chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel",
"target": "conversationalAgent_0",
"targetHandle": "conversationalAgent_0-input-model-BaseLanguageModel",
"type": "buttonedge",
"id": "chatOpenAI_1-chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-conversationalAgent_0-conversationalAgent_0-input-model-BaseLanguageModel",
"data": {
"label": ""
}
},
{
"source": "webBrowser_0",
"sourceHandle": "webBrowser_0-output-webBrowser-WebBrowser|Tool|StructuredTool|BaseLangChain",
@@ -660,6 +649,17 @@
"label": ""
}
},
{
"source": "chatOpenAI_1",
"sourceHandle": "chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel",
"target": "conversationalAgent_0",
"targetHandle": "conversationalAgent_0-input-model-BaseChatModel",
"type": "buttonedge",
"id": "chatOpenAI_1-chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-conversationalAgent_0-conversationalAgent_0-input-model-BaseChatModel",
"data": {
"label": ""
}
},
{
"source": "bufferMemory_0",
"sourceHandle": "bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "flowise",
"version": "1.4.2",
"version": "1.4.3",
"description": "Flowiseai Server",
"main": "dist/index",
"types": "dist/index.d.ts",
-6
View File
@@ -190,12 +190,6 @@ export interface IOverrideConfig {
type: string
}
export interface IDatabaseExport {
chatmessages: IChatMessage[]
chatflows: IChatFlow[]
apikeys: ICommonObject[]
}
export type ICredentialDataDecrypted = ICommonObject
// Plain credential object sent to server
+1 -59
View File
@@ -17,7 +17,6 @@ import {
IReactFlowNode,
IReactFlowObject,
INodeData,
IDatabaseExport,
ICredentialReturnResponse,
chatType,
IChatMessage,
@@ -31,18 +30,11 @@ import {
constructGraphs,
resolveVariables,
isStartNodeDependOnInput,
getAPIKeys,
addAPIKey,
updateAPIKey,
deleteAPIKey,
compareKeys,
mapMimeTypeToInputField,
findAvailableConfigs,
isSameOverrideConfig,
replaceAllAPIKeys,
isFlowValidForStream,
databaseEntities,
getApiKey,
transformToCredentialEntity,
decryptCredentialData,
clearAllSessionMemory,
@@ -64,6 +56,7 @@ import { ChatflowPool } from './ChatflowPool'
import { CachePool } from './CachePool'
import { ICommonObject, INodeOptionsValue } from 'flowise-components'
import { createRateLimiter, getRateLimiter, initializeRateLimiter } from './utils/rateLimit'
import { addAPIKey, compareKeys, deleteAPIKey, getApiKey, getAPIKeys, updateAPIKey } from './utils/apiKey'
export class App {
app: express.Application
@@ -1025,57 +1018,6 @@ export class App {
}
})
// ----------------------------------------
// Export Load Chatflow & ChatMessage & Apikeys
// ----------------------------------------
this.app.get('/api/v1/database/export', async (req: Request, res: Response) => {
const chatmessages = await this.AppDataSource.getRepository(ChatMessage).find()
const chatflows = await this.AppDataSource.getRepository(ChatFlow).find()
const apikeys = await getAPIKeys()
const result: IDatabaseExport = {
chatmessages,
chatflows,
apikeys
}
return res.json(result)
})
this.app.post('/api/v1/database/load', async (req: Request, res: Response) => {
const databaseItems: IDatabaseExport = req.body
await this.AppDataSource.getRepository(ChatFlow).delete({})
await this.AppDataSource.getRepository(ChatMessage).delete({})
let error = ''
// Get a new query runner instance
const queryRunner = this.AppDataSource.createQueryRunner()
// Start a new transaction
await queryRunner.startTransaction()
try {
const chatflows: ChatFlow[] = databaseItems.chatflows
const chatmessages: ChatMessage[] = databaseItems.chatmessages
await queryRunner.manager.insert(ChatFlow, chatflows)
await queryRunner.manager.insert(ChatMessage, chatmessages)
await queryRunner.commitTransaction()
} catch (err: any) {
error = err?.message ?? 'Error loading database'
await queryRunner.rollbackTransaction()
} finally {
await queryRunner.release()
}
await replaceAllAPIKeys(databaseItems.apikeys)
if (error) return res.status(500).send(error)
return res.status(201).send('OK')
})
// ----------------------------------------
// Upsert
// ----------------------------------------
+147
View File
@@ -0,0 +1,147 @@
import { randomBytes, scryptSync, timingSafeEqual } from 'crypto'
import { ICommonObject } from 'flowise-components'
import moment from 'moment'
import fs from 'fs'
import path from 'path'
import logger from './logger'
/**
* Returns the api key path
* @returns {string}
*/
export const getAPIKeyPath = (): string => {
return process.env.APIKEY_PATH ? path.join(process.env.APIKEY_PATH, 'api.json') : path.join(__dirname, '..', '..', 'api.json')
}
/**
* Generate the api key
* @returns {string}
*/
export const generateAPIKey = (): string => {
const buffer = randomBytes(32)
return buffer.toString('base64')
}
/**
* Generate the secret key
* @param {string} apiKey
* @returns {string}
*/
export const generateSecretHash = (apiKey: string): string => {
const salt = randomBytes(8).toString('hex')
const buffer = scryptSync(apiKey, salt, 64) as Buffer
return `${buffer.toString('hex')}.${salt}`
}
/**
* Verify valid keys
* @param {string} storedKey
* @param {string} suppliedKey
* @returns {boolean}
*/
export const compareKeys = (storedKey: string, suppliedKey: string): boolean => {
const [hashedPassword, salt] = storedKey.split('.')
const buffer = scryptSync(suppliedKey, salt, 64) as Buffer
return timingSafeEqual(Buffer.from(hashedPassword, 'hex'), buffer)
}
/**
* Get API keys
* @returns {Promise<ICommonObject[]>}
*/
export const getAPIKeys = async (): Promise<ICommonObject[]> => {
try {
const content = await fs.promises.readFile(getAPIKeyPath(), 'utf8')
return JSON.parse(content)
} catch (error) {
const keyName = 'DefaultKey'
const apiKey = generateAPIKey()
const apiSecret = generateSecretHash(apiKey)
const content = [
{
keyName,
apiKey,
apiSecret,
createdAt: moment().format('DD-MMM-YY'),
id: randomBytes(16).toString('hex')
}
]
await fs.promises.writeFile(getAPIKeyPath(), JSON.stringify(content), 'utf8')
return content
}
}
/**
* Add new API key
* @param {string} keyName
* @returns {Promise<ICommonObject[]>}
*/
export const addAPIKey = async (keyName: string): Promise<ICommonObject[]> => {
const existingAPIKeys = await getAPIKeys()
const apiKey = generateAPIKey()
const apiSecret = generateSecretHash(apiKey)
const content = [
...existingAPIKeys,
{
keyName,
apiKey,
apiSecret,
createdAt: moment().format('DD-MMM-YY'),
id: randomBytes(16).toString('hex')
}
]
await fs.promises.writeFile(getAPIKeyPath(), JSON.stringify(content), 'utf8')
return content
}
/**
* Get API Key details
* @param {string} apiKey
* @returns {Promise<ICommonObject[]>}
*/
export const getApiKey = async (apiKey: string) => {
const existingAPIKeys = await getAPIKeys()
const keyIndex = existingAPIKeys.findIndex((key) => key.apiKey === apiKey)
if (keyIndex < 0) return undefined
return existingAPIKeys[keyIndex]
}
/**
* Update existing API key
* @param {string} keyIdToUpdate
* @param {string} newKeyName
* @returns {Promise<ICommonObject[]>}
*/
export const updateAPIKey = async (keyIdToUpdate: string, newKeyName: string): Promise<ICommonObject[]> => {
const existingAPIKeys = await getAPIKeys()
const keyIndex = existingAPIKeys.findIndex((key) => key.id === keyIdToUpdate)
if (keyIndex < 0) return []
existingAPIKeys[keyIndex].keyName = newKeyName
await fs.promises.writeFile(getAPIKeyPath(), JSON.stringify(existingAPIKeys), 'utf8')
return existingAPIKeys
}
/**
* Delete API key
* @param {string} keyIdToDelete
* @returns {Promise<ICommonObject[]>}
*/
export const deleteAPIKey = async (keyIdToDelete: string): Promise<ICommonObject[]> => {
const existingAPIKeys = await getAPIKeys()
const result = existingAPIKeys.filter((key) => key.id !== keyIdToDelete)
await fs.promises.writeFile(getAPIKeyPath(), JSON.stringify(result), 'utf8')
return result
}
/**
* Replace all api keys
* @param {ICommonObject[]} content
* @returns {Promise<void>}
*/
export const replaceAllAPIKeys = async (content: ICommonObject[]): Promise<void> => {
try {
await fs.promises.writeFile(getAPIKeyPath(), JSON.stringify(content), 'utf8')
} catch (error) {
logger.error(error)
}
}
+12 -154
View File
@@ -1,33 +1,32 @@
import path from 'path'
import fs from 'fs'
import moment from 'moment'
import logger from './logger'
import {
IComponentCredentials,
IComponentNodes,
ICredentialDataDecrypted,
ICredentialReqBody,
IDepthQueue,
IExploredNode,
INodeData,
INodeDependencies,
INodeDirectedGraph,
INodeQueue,
IOverrideConfig,
IReactFlowEdge,
IReactFlowNode,
IVariableDict,
INodeData,
IOverrideConfig,
ICredentialDataDecrypted,
IComponentCredentials,
ICredentialReqBody
IVariableDict
} from '../Interface'
import { cloneDeep, get, isEqual } from 'lodash'
import {
ICommonObject,
convertChatHistoryToText,
getInputVariables,
IDatabaseEntity,
handleEscapeCharacters,
IMessage,
convertChatHistoryToText
ICommonObject,
IDatabaseEntity,
IMessage
} from 'flowise-components'
import { scryptSync, randomBytes, timingSafeEqual } from 'crypto'
import { randomBytes } from 'crypto'
import { AES, enc } from 'crypto-js'
import { ChatFlow } from '../database/entities/ChatFlow'
@@ -593,147 +592,6 @@ export const isSameOverrideConfig = (
return false
}
/**
* Returns the api key path
* @returns {string}
*/
export const getAPIKeyPath = (): string => {
return process.env.APIKEY_PATH ? path.join(process.env.APIKEY_PATH, 'api.json') : path.join(__dirname, '..', '..', 'api.json')
}
/**
* Generate the api key
* @returns {string}
*/
export const generateAPIKey = (): string => {
const buffer = randomBytes(32)
return buffer.toString('base64')
}
/**
* Generate the secret key
* @param {string} apiKey
* @returns {string}
*/
export const generateSecretHash = (apiKey: string): string => {
const salt = randomBytes(8).toString('hex')
const buffer = scryptSync(apiKey, salt, 64) as Buffer
return `${buffer.toString('hex')}.${salt}`
}
/**
* Verify valid keys
* @param {string} storedKey
* @param {string} suppliedKey
* @returns {boolean}
*/
export const compareKeys = (storedKey: string, suppliedKey: string): boolean => {
const [hashedPassword, salt] = storedKey.split('.')
const buffer = scryptSync(suppliedKey, salt, 64) as Buffer
return timingSafeEqual(Buffer.from(hashedPassword, 'hex'), buffer)
}
/**
* Get API keys
* @returns {Promise<ICommonObject[]>}
*/
export const getAPIKeys = async (): Promise<ICommonObject[]> => {
try {
const content = await fs.promises.readFile(getAPIKeyPath(), 'utf8')
return JSON.parse(content)
} catch (error) {
const keyName = 'DefaultKey'
const apiKey = generateAPIKey()
const apiSecret = generateSecretHash(apiKey)
const content = [
{
keyName,
apiKey,
apiSecret,
createdAt: moment().format('DD-MMM-YY'),
id: randomBytes(16).toString('hex')
}
]
await fs.promises.writeFile(getAPIKeyPath(), JSON.stringify(content), 'utf8')
return content
}
}
/**
* Add new API key
* @param {string} keyName
* @returns {Promise<ICommonObject[]>}
*/
export const addAPIKey = async (keyName: string): Promise<ICommonObject[]> => {
const existingAPIKeys = await getAPIKeys()
const apiKey = generateAPIKey()
const apiSecret = generateSecretHash(apiKey)
const content = [
...existingAPIKeys,
{
keyName,
apiKey,
apiSecret,
createdAt: moment().format('DD-MMM-YY'),
id: randomBytes(16).toString('hex')
}
]
await fs.promises.writeFile(getAPIKeyPath(), JSON.stringify(content), 'utf8')
return content
}
/**
* Get API Key details
* @param {string} apiKey
* @returns {Promise<ICommonObject[]>}
*/
export const getApiKey = async (apiKey: string) => {
const existingAPIKeys = await getAPIKeys()
const keyIndex = existingAPIKeys.findIndex((key) => key.apiKey === apiKey)
if (keyIndex < 0) return undefined
return existingAPIKeys[keyIndex]
}
/**
* Update existing API key
* @param {string} keyIdToUpdate
* @param {string} newKeyName
* @returns {Promise<ICommonObject[]>}
*/
export const updateAPIKey = async (keyIdToUpdate: string, newKeyName: string): Promise<ICommonObject[]> => {
const existingAPIKeys = await getAPIKeys()
const keyIndex = existingAPIKeys.findIndex((key) => key.id === keyIdToUpdate)
if (keyIndex < 0) return []
existingAPIKeys[keyIndex].keyName = newKeyName
await fs.promises.writeFile(getAPIKeyPath(), JSON.stringify(existingAPIKeys), 'utf8')
return existingAPIKeys
}
/**
* Delete API key
* @param {string} keyIdToDelete
* @returns {Promise<ICommonObject[]>}
*/
export const deleteAPIKey = async (keyIdToDelete: string): Promise<ICommonObject[]> => {
const existingAPIKeys = await getAPIKeys()
const result = existingAPIKeys.filter((key) => key.id !== keyIdToDelete)
await fs.promises.writeFile(getAPIKeyPath(), JSON.stringify(result), 'utf8')
return result
}
/**
* Replace all api keys
* @param {ICommonObject[]} content
* @returns {Promise<void>}
*/
export const replaceAllAPIKeys = async (content: ICommonObject[]): Promise<void> => {
try {
await fs.promises.writeFile(getAPIKeyPath(), JSON.stringify(content), 'utf8')
} catch (error) {
logger.error(error)
}
}
/**
* Map MimeType to InputField
* @param {string} mimeType
@@ -844,7 +702,7 @@ export const findAvailableConfigs = (reactFlowNodes: IReactFlowNode[], component
*/
export const isFlowValidForStream = (reactFlowNodes: IReactFlowNode[], endingNodeData: INodeData) => {
const streamAvailableLLMs = {
'Chat Models': ['azureChatOpenAI', 'chatOpenAI', 'chatAnthropic', 'chatOllama'],
'Chat Models': ['azureChatOpenAI', 'chatOpenAI', 'chatAnthropic', 'chatOllama', 'awsChatBedrock'],
LLMs: ['azureOpenAI', 'openAI', 'ollama']
}