diff --git a/packages/components/nodes/chains/LLMChain/LLMChain.ts b/packages/components/nodes/chains/LLMChain/LLMChain.ts index 9cd08d35303..67c21ce457b 100644 --- a/packages/components/nodes/chains/LLMChain/LLMChain.ts +++ b/packages/components/nodes/chains/LLMChain/LLMChain.ts @@ -50,7 +50,7 @@ class LLMChain_Chains implements INode { { label: 'Output Prediction', name: 'outputPrediction', - baseClasses: ['string'] + baseClasses: ['string', 'json'] } ] } diff --git a/packages/components/nodes/prompts/ChatPromptTemplate/ChatPromptTemplate.ts b/packages/components/nodes/prompts/ChatPromptTemplate/ChatPromptTemplate.ts index c3c4d77f686..4eeb1dd23a7 100644 --- a/packages/components/nodes/prompts/ChatPromptTemplate/ChatPromptTemplate.ts +++ b/packages/components/nodes/prompts/ChatPromptTemplate/ChatPromptTemplate.ts @@ -38,12 +38,7 @@ class ChatPromptTemplate_Prompts implements INode { { label: 'Format Prompt Values', name: 'promptValues', - type: 'string', - rows: 4, - placeholder: `{ - "input_language": "English", - "output_language": "French" -}`, + type: 'json', optional: true, acceptVariable: true, list: true diff --git a/packages/components/nodes/prompts/PromptTemplate/PromptTemplate.ts b/packages/components/nodes/prompts/PromptTemplate/PromptTemplate.ts index f976d64c670..f9c6c53e3b5 100644 --- a/packages/components/nodes/prompts/PromptTemplate/PromptTemplate.ts +++ b/packages/components/nodes/prompts/PromptTemplate/PromptTemplate.ts @@ -31,12 +31,7 @@ class PromptTemplate_Prompts implements INode { { label: 'Format Prompt Values', name: 'promptValues', - type: 'string', - rows: 4, - placeholder: `{ - "input_language": "English", - "output_language": "French" -}`, + type: 'json', optional: true, acceptVariable: true, list: true diff --git a/packages/components/src/utils.ts b/packages/components/src/utils.ts index ad8d28dca08..c247ebc2c32 100644 --- a/packages/components/src/utils.ts +++ b/packages/components/src/utils.ts @@ -245,47 +245,6 @@ export class CustomChainHandler extends BaseCallbackHandler { } } -export const returnJSONStr = (jsonStr: string): string => { - let jsonStrArray = jsonStr.split(':') - - let wholeString = '' - for (let i = 0; i < jsonStrArray.length; i++) { - if (jsonStrArray[i].includes(',') && jsonStrArray[i + 1] !== undefined) { - const splitValueAndTitle = jsonStrArray[i].split(',') - const value = splitValueAndTitle[0] - const newTitle = splitValueAndTitle[1] - wholeString += handleEscapeDoubleQuote(value) + ',' + newTitle + ':' - } else { - wholeString += wholeString === '' ? jsonStrArray[i] + ':' : handleEscapeDoubleQuote(jsonStrArray[i]) - } - } - return wholeString -} - -const handleEscapeDoubleQuote = (value: string): string => { - let newValue = '' - if (value.includes('"')) { - const valueArray = value.split('"') - for (let i = 0; i < valueArray.length; i++) { - if ((i + 1) % 2 !== 0) { - switch (valueArray[i]) { - case '': - newValue += '"' - break - case '}': - newValue += '"}' - break - default: - newValue += '\\"' + valueArray[i] + '\\"' - } - } else { - newValue += valueArray[i] - } - } - } - return newValue === '' ? value : newValue -} - export const availableDependencies = [ '@dqbd/tiktoken', '@getzep/zep-js', diff --git a/packages/server/marketplaces/Antonym.json b/packages/server/marketplaces/Antonym.json index 2e21fd221e3..817e3ee90e7 100644 --- a/packages/server/marketplaces/Antonym.json +++ b/packages/server/marketplaces/Antonym.json @@ -3,68 +3,7 @@ "nodes": [ { "width": 300, - "height": 534, - "id": "promptTemplate_1", - "position": { - "x": 532.2791692529131, - "y": -31.128527027841372 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_1", - "label": "Prompt Template", - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_1-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "string", - "rows": 4, - "placeholder": "{\n \"input_language\": \"English\",\n \"output_language\": \"French\"\n}", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_1-input-promptValues-string" - } - ], - "inputAnchors": [], - "inputs": { - "template": "Word: {word}\\nAntonym: {antonym}\\n", - "promptValues": "" - }, - "outputAnchors": [ - { - "id": "promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 532.2791692529131, - "y": -31.128527027841372 - }, - "dragging": false - }, - { - "width": 300, - "height": 956, + "height": 955, "id": "fewShotPromptTemplate_1", "position": { "x": 886.3229032369354, @@ -139,7 +78,7 @@ ], "inputs": { "examples": "[\n { \"word\": \"happy\", \"antonym\": \"sad\" },\n { \"word\": \"tall\", \"antonym\": \"short\" }\n]", - "examplePrompt": "{{promptTemplate_1.data.instance}}", + "examplePrompt": "{{promptTemplate_0.data.instance}}", "prefix": "Give the antonym of every input", "suffix": "Word: {input}\\nAntonym:", "exampleSeparator": "\\n\\n", @@ -165,7 +104,7 @@ }, { "width": 300, - "height": 526, + "height": 524, "id": "openAI_1", "position": { "x": 1224.5139327142097, @@ -318,7 +257,7 @@ }, { "width": 300, - "height": 407, + "height": 405, "id": "llmChain_1", "position": { "x": 1635.363191180743, @@ -375,10 +314,10 @@ "type": "LLMChain | BaseChain | BaseLangChain" }, { - "id": "llmChain_1-output-outputPrediction-string", + "id": "llmChain_1-output-outputPrediction-string|json", "name": "outputPrediction", "label": "Output Prediction", - "type": "string" + "type": "string | json" } ], "default": "llmChain" @@ -395,20 +334,68 @@ }, "selected": false, "dragging": false + }, + { + "width": 300, + "height": 475, + "id": "promptTemplate_0", + "position": { + "x": 540.0140796251119, + "y": -33.31673494170347 + }, + "type": "customNode", + "data": { + "id": "promptTemplate_0", + "label": "Prompt Template", + "name": "promptTemplate", + "type": "PromptTemplate", + "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], + "category": "Prompts", + "description": "Schema to represent a basic prompt for an LLM", + "inputParams": [ + { + "label": "Template", + "name": "template", + "type": "string", + "rows": 4, + "placeholder": "What is a good name for a company that makes {product}?", + "id": "promptTemplate_0-input-template-string" + }, + { + "label": "Format Prompt Values", + "name": "promptValues", + "type": "json", + "optional": true, + "acceptVariable": true, + "list": true, + "id": "promptTemplate_0-input-promptValues-json" + } + ], + "inputAnchors": [], + "inputs": { + "template": "Word: {word}\\nAntonym: {antonym}\\n", + "promptValues": "" + }, + "outputAnchors": [ + { + "id": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", + "name": "promptTemplate", + "label": "PromptTemplate", + "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" + } + ], + "outputs": {}, + "selected": false + }, + "selected": false, + "positionAbsolute": { + "x": 540.0140796251119, + "y": -33.31673494170347 + }, + "dragging": false } ], "edges": [ - { - "source": "promptTemplate_1", - "sourceHandle": "promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "target": "fewShotPromptTemplate_1", - "targetHandle": "fewShotPromptTemplate_1-input-examplePrompt-PromptTemplate", - "type": "buttonedge", - "id": "promptTemplate_1-promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-fewShotPromptTemplate_1-fewShotPromptTemplate_1-input-examplePrompt-PromptTemplate", - "data": { - "label": "" - } - }, { "source": "openAI_1", "sourceHandle": "openAI_1-output-openAI-OpenAI|BaseLLM|BaseLanguageModel|BaseLangChain", @@ -430,6 +417,17 @@ "data": { "label": "" } + }, + { + "source": "promptTemplate_0", + "sourceHandle": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", + "target": "fewShotPromptTemplate_1", + "targetHandle": "fewShotPromptTemplate_1-input-examplePrompt-PromptTemplate", + "type": "buttonedge", + "id": "promptTemplate_0-promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-fewShotPromptTemplate_1-fewShotPromptTemplate_1-input-examplePrompt-PromptTemplate", + "data": { + "label": "" + } } ] } diff --git a/packages/server/marketplaces/HuggingFace LLM Chain.json b/packages/server/marketplaces/HuggingFace LLM Chain.json index 9d3492c6b95..d46f9d643ba 100644 --- a/packages/server/marketplaces/HuggingFace LLM Chain.json +++ b/packages/server/marketplaces/HuggingFace LLM Chain.json @@ -1,67 +1,6 @@ { "description": "Simple LLM Chain using HuggingFace Inference API on falcon-7b-instruct model", "nodes": [ - { - "width": 300, - "height": 532, - "id": "promptTemplate_1", - "position": { - "x": 514.5434056794296, - "y": 507.47798128037107 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_1", - "label": "Prompt Template", - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_1-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "string", - "rows": 4, - "placeholder": "{\n \"input_language\": \"English\",\n \"output_language\": \"French\"\n}", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_1-input-promptValues-string" - } - ], - "inputAnchors": [], - "inputs": { - "template": "Question: {question}\n\nAnswer: Let's think step by step.", - "promptValues": "" - }, - "outputAnchors": [ - { - "id": "promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 514.5434056794296, - "y": 507.47798128037107 - }, - "dragging": false - }, { "width": 300, "height": 405, @@ -105,7 +44,7 @@ ], "inputs": { "model": "{{huggingFaceInference_LLMs_0.data.instance}}", - "prompt": "{{promptTemplate_1.data.instance}}", + "prompt": "{{promptTemplate_0.data.instance}}", "chainName": "" }, "outputAnchors": [ @@ -121,10 +60,10 @@ "type": "LLMChain | BaseChain | BaseLangChain" }, { - "id": "llmChain_1-output-outputPrediction-string", + "id": "llmChain_1-output-outputPrediction-string|json", "name": "outputPrediction", "label": "Output Prediction", - "type": "string" + "type": "string | json" } ], "default": "llmChain" @@ -144,7 +83,7 @@ }, { "width": 300, - "height": 427, + "height": 429, "id": "huggingFaceInference_LLMs_0", "position": { "x": 503.5630827259226, @@ -245,27 +184,86 @@ "y": 50.79125094823999 }, "dragging": false + }, + { + "width": 300, + "height": 475, + "id": "promptTemplate_0", + "position": { + "x": 506.50436294210306, + "y": 504.50766458127396 + }, + "type": "customNode", + "data": { + "id": "promptTemplate_0", + "label": "Prompt Template", + "name": "promptTemplate", + "type": "PromptTemplate", + "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], + "category": "Prompts", + "description": "Schema to represent a basic prompt for an LLM", + "inputParams": [ + { + "label": "Template", + "name": "template", + "type": "string", + "rows": 4, + "placeholder": "What is a good name for a company that makes {product}?", + "id": "promptTemplate_0-input-template-string" + }, + { + "label": "Format Prompt Values", + "name": "promptValues", + "type": "json", + "optional": true, + "acceptVariable": true, + "list": true, + "id": "promptTemplate_0-input-promptValues-json" + } + ], + "inputAnchors": [], + "inputs": { + "template": "Question: {question}\n\nAnswer: Let's think step by step.", + "promptValues": "" + }, + "outputAnchors": [ + { + "id": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", + "name": "promptTemplate", + "label": "PromptTemplate", + "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" + } + ], + "outputs": {}, + "selected": false + }, + "selected": false, + "positionAbsolute": { + "x": 506.50436294210306, + "y": 504.50766458127396 + }, + "dragging": false } ], "edges": [ { - "source": "promptTemplate_1", - "sourceHandle": "promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", + "source": "huggingFaceInference_LLMs_0", + "sourceHandle": "huggingFaceInference_LLMs_0-output-huggingFaceInference_LLMs-HuggingFaceInference|LLM|BaseLLM|BaseLanguageModel|BaseLangChain", "target": "llmChain_1", - "targetHandle": "llmChain_1-input-prompt-BasePromptTemplate", + "targetHandle": "llmChain_1-input-model-BaseLanguageModel", "type": "buttonedge", - "id": "promptTemplate_1-promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_1-llmChain_1-input-prompt-BasePromptTemplate", + "id": "huggingFaceInference_LLMs_0-huggingFaceInference_LLMs_0-output-huggingFaceInference_LLMs-HuggingFaceInference|LLM|BaseLLM|BaseLanguageModel|BaseLangChain-llmChain_1-llmChain_1-input-model-BaseLanguageModel", "data": { "label": "" } }, { - "source": "huggingFaceInference_LLMs_0", - "sourceHandle": "huggingFaceInference_LLMs_0-output-huggingFaceInference_LLMs-HuggingFaceInference|LLM|BaseLLM|BaseLanguageModel|BaseLangChain", + "source": "promptTemplate_0", + "sourceHandle": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", "target": "llmChain_1", - "targetHandle": "llmChain_1-input-model-BaseLanguageModel", + "targetHandle": "llmChain_1-input-prompt-BasePromptTemplate", "type": "buttonedge", - "id": "huggingFaceInference_LLMs_0-huggingFaceInference_LLMs_0-output-huggingFaceInference_LLMs-HuggingFaceInference|LLM|BaseLLM|BaseLanguageModel|BaseLangChain-llmChain_1-llmChain_1-input-model-BaseLanguageModel", + "id": "promptTemplate_0-promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_1-llmChain_1-input-prompt-BasePromptTemplate", "data": { "label": "" } diff --git a/packages/server/marketplaces/Prompt Chaining.json b/packages/server/marketplaces/Prompt Chaining.json index 33a64081aec..96987660e8f 100644 --- a/packages/server/marketplaces/Prompt Chaining.json +++ b/packages/server/marketplaces/Prompt Chaining.json @@ -3,7 +3,7 @@ "nodes": [ { "width": 300, - "height": 526, + "height": 524, "id": "openAI_2", "position": { "x": 793.6674026500068, @@ -156,213 +156,11 @@ }, { "width": 300, - "height": 534, - "id": "promptTemplate_2", - "position": { - "x": 796.3399644963663, - "y": 512.349657546027 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_2", - "label": "Prompt Template", - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_2-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "string", - "rows": 4, - "placeholder": "{\n \"input_language\": \"English\",\n \"output_language\": \"French\"\n}", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_2-input-promptValues-string" - } - ], - "inputAnchors": [], - "inputs": { - "template": "You are an AI who performs one task based on the following objective: {objective}.\nRespond with how you would complete this task:", - "promptValues": "{\n \"objective\": \"{{question}}\"\n}" - }, - "outputAnchors": [ - { - "id": "promptTemplate_2-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 796.3399644963663, - "y": 512.349657546027 - }, - "dragging": false - }, - { - "width": 300, - "height": 407, - "id": "llmChain_2", - "position": { - "x": 1225.2861408370582, - "y": 485.62403908243243 - }, - "type": "customNode", - "data": { - "id": "llmChain_2", - "label": "LLM Chain", - "name": "llmChain", - "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "BaseLangChain"], - "category": "Chains", - "description": "Chain to run queries against LLMs", - "inputParams": [ - { - "label": "Chain Name", - "name": "chainName", - "type": "string", - "placeholder": "Name Your Chain", - "optional": true, - "id": "llmChain_2-input-chainName-string" - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "llmChain_2-input-model-BaseLanguageModel" - }, - { - "label": "Prompt", - "name": "prompt", - "type": "BasePromptTemplate", - "id": "llmChain_2-input-prompt-BasePromptTemplate" - } - ], - "inputs": { - "model": "{{openAI_2.data.instance}}", - "prompt": "{{promptTemplate_2.data.instance}}", - "chainName": "First Chain" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "llmChain_2-output-llmChain-LLMChain|BaseChain|BaseLangChain", - "name": "llmChain", - "label": "LLM Chain", - "type": "LLMChain | BaseChain | BaseLangChain" - }, - { - "id": "llmChain_2-output-outputPrediction-string", - "name": "outputPrediction", - "label": "Output Prediction", - "type": "string" - } - ], - "default": "llmChain" - } - ], - "outputs": { - "output": "outputPrediction" - }, - "selected": false - }, - "selected": false, - "dragging": false, - "positionAbsolute": { - "x": 1225.2861408370582, - "y": 485.62403908243243 - } - }, - { - "width": 300, - "height": 534, - "id": "promptTemplate_3", - "position": { - "x": 1589.206555911206, - "y": 460.23470154201766 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_3", - "label": "Prompt Template", - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_3-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "string", - "rows": 4, - "placeholder": "{\n \"input_language\": \"English\",\n \"output_language\": \"French\"\n}", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_3-input-promptValues-string" - } - ], - "inputAnchors": [], - "inputs": { - "template": "You are a task creation AI that uses the result of an execution agent to create new tasks with the following objective: {objective}.\nThe last completed task has the result: {result}.\nBased on the result, create new tasks to be completed by the AI system that do not overlap with result.\nReturn the tasks as an array.", - "promptValues": "{\n \"objective\": \"{{question}}\",\n \"result\": \"\"\n}" - }, - "outputAnchors": [ - { - "id": "promptTemplate_3-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1589.206555911206, - "y": 460.23470154201766 - }, - "dragging": false - }, - { - "width": 300, - "height": 526, + "height": 524, "id": "openAI_3", "position": { - "x": 1225.2861408370586, - "y": -62.7856517905272 + "x": 1216.061423775753, + "y": -20.35195330852082 }, "type": "customNode", "data": { @@ -503,27 +301,145 @@ "selected": false }, "positionAbsolute": { - "x": 1225.2861408370586, - "y": -62.7856517905272 + "x": 1216.061423775753, + "y": -20.35195330852082 + }, + "selected": false, + "dragging": false + }, + { + "width": 300, + "height": 475, + "id": "promptTemplate_0", + "position": { + "x": 792.9464838535649, + "y": 527.1718536712464 + }, + "type": "customNode", + "data": { + "id": "promptTemplate_0", + "label": "Prompt Template", + "name": "promptTemplate", + "type": "PromptTemplate", + "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], + "category": "Prompts", + "description": "Schema to represent a basic prompt for an LLM", + "inputParams": [ + { + "label": "Template", + "name": "template", + "type": "string", + "rows": 4, + "placeholder": "What is a good name for a company that makes {product}?", + "id": "promptTemplate_0-input-template-string" + }, + { + "label": "Format Prompt Values", + "name": "promptValues", + "type": "json", + "optional": true, + "acceptVariable": true, + "list": true, + "id": "promptTemplate_0-input-promptValues-json" + } + ], + "inputAnchors": [], + "inputs": { + "template": "You are an AI who performs one task based on the following objective: {objective}.\nRespond with how you would complete this task:", + "promptValues": "{\"objective\":\"{{question}}\"}" + }, + "outputAnchors": [ + { + "id": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", + "name": "promptTemplate", + "label": "PromptTemplate", + "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" + } + ], + "outputs": {}, + "selected": false + }, + "selected": false, + "positionAbsolute": { + "x": 792.9464838535649, + "y": 527.1718536712464 + }, + "dragging": false + }, + { + "width": 300, + "height": 475, + "id": "promptTemplate_1", + "position": { + "x": 1577.7482561604884, + "y": 516.186942924815 + }, + "type": "customNode", + "data": { + "id": "promptTemplate_1", + "label": "Prompt Template", + "name": "promptTemplate", + "type": "PromptTemplate", + "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], + "category": "Prompts", + "description": "Schema to represent a basic prompt for an LLM", + "inputParams": [ + { + "label": "Template", + "name": "template", + "type": "string", + "rows": 4, + "placeholder": "What is a good name for a company that makes {product}?", + "id": "promptTemplate_1-input-template-string" + }, + { + "label": "Format Prompt Values", + "name": "promptValues", + "type": "json", + "optional": true, + "acceptVariable": true, + "list": true, + "id": "promptTemplate_1-input-promptValues-json" + } + ], + "inputAnchors": [], + "inputs": { + "template": "You are a task creation AI that uses the result of an execution agent to create new tasks with the following objective: {objective}.\nThe last completed task has the result: {result}.\nBased on the result, create new tasks to be completed by the AI system that do not overlap with result.\nReturn the tasks as an array.", + "promptValues": "{\"objective\":\"{{question}}\",\"result\":\"{{llmChain_0.data.instance}}\"}" + }, + "outputAnchors": [ + { + "id": "promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", + "name": "promptTemplate", + "label": "PromptTemplate", + "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" + } + ], + "outputs": {}, + "selected": false + }, + "positionAbsolute": { + "x": 1577.7482561604884, + "y": 516.186942924815 }, "selected": false, "dragging": false }, { "width": 300, - "height": 407, - "id": "llmChain_3", + "height": 405, + "id": "llmChain_0", "position": { - "x": 1972.2671768945252, - "y": 142.73435419451476 + "x": 1221.1346231272787, + "y": 538.9546839784628 }, "type": "customNode", "data": { - "id": "llmChain_3", + "id": "llmChain_0", "label": "LLM Chain", "name": "llmChain", "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "BaseLangChain"], + "baseClasses": ["LLMChain", "BaseChain"], "category": "Chains", "description": "Chain to run queries against LLMs", "inputParams": [ @@ -533,7 +449,7 @@ "type": "string", "placeholder": "Name Your Chain", "optional": true, - "id": "llmChain_3-input-chainName-string" + "id": "llmChain_0-input-chainName-string" } ], "inputAnchors": [ @@ -541,18 +457,98 @@ "label": "Language Model", "name": "model", "type": "BaseLanguageModel", - "id": "llmChain_3-input-model-BaseLanguageModel" + "id": "llmChain_0-input-model-BaseLanguageModel" }, { "label": "Prompt", "name": "prompt", "type": "BasePromptTemplate", - "id": "llmChain_3-input-prompt-BasePromptTemplate" + "id": "llmChain_0-input-prompt-BasePromptTemplate" + } + ], + "inputs": { + "model": "{{openAI_2.data.instance}}", + "prompt": "{{promptTemplate_0.data.instance}}", + "chainName": "FirstChain" + }, + "outputAnchors": [ + { + "name": "output", + "label": "Output", + "type": "options", + "options": [ + { + "id": "llmChain_0-output-llmChain-LLMChain|BaseChain", + "name": "llmChain", + "label": "LLM Chain", + "type": "LLMChain | BaseChain" + }, + { + "id": "llmChain_0-output-outputPrediction-string|json", + "name": "outputPrediction", + "label": "Output Prediction", + "type": "string | json" + } + ], + "default": "llmChain" + } + ], + "outputs": { + "output": "outputPrediction" + }, + "selected": false + }, + "selected": false, + "positionAbsolute": { + "x": 1221.1346231272787, + "y": 538.9546839784628 + }, + "dragging": false + }, + { + "width": 300, + "height": 405, + "id": "llmChain_1", + "position": { + "x": 1971.8054567964418, + "y": 207.624530381245 + }, + "type": "customNode", + "data": { + "id": "llmChain_1", + "label": "LLM Chain", + "name": "llmChain", + "type": "LLMChain", + "baseClasses": ["LLMChain", "BaseChain"], + "category": "Chains", + "description": "Chain to run queries against LLMs", + "inputParams": [ + { + "label": "Chain Name", + "name": "chainName", + "type": "string", + "placeholder": "Name Your Chain", + "optional": true, + "id": "llmChain_1-input-chainName-string" + } + ], + "inputAnchors": [ + { + "label": "Language Model", + "name": "model", + "type": "BaseLanguageModel", + "id": "llmChain_1-input-model-BaseLanguageModel" + }, + { + "label": "Prompt", + "name": "prompt", + "type": "BasePromptTemplate", + "id": "llmChain_1-input-prompt-BasePromptTemplate" } ], "inputs": { "model": "{{openAI_3.data.instance}}", - "prompt": "{{promptTemplate_3.data.instance}}", + "prompt": "{{promptTemplate_1.data.instance}}", "chainName": "LastChain" }, "outputAnchors": [ @@ -562,16 +558,16 @@ "type": "options", "options": [ { - "id": "llmChain_3-output-llmChain-LLMChain|BaseChain|BaseLangChain", + "id": "llmChain_1-output-llmChain-LLMChain|BaseChain", "name": "llmChain", "label": "LLM Chain", - "type": "LLMChain | BaseChain | BaseLangChain" + "type": "LLMChain | BaseChain" }, { - "id": "llmChain_3-output-outputPrediction-string", + "id": "llmChain_1-output-outputPrediction-string|json", "name": "outputPrediction", "label": "Output Prediction", - "type": "string" + "type": "string | json" } ], "default": "llmChain" @@ -583,43 +579,43 @@ "selected": false }, "selected": false, - "dragging": false, "positionAbsolute": { - "x": 1972.2671768945252, - "y": 142.73435419451476 - } + "x": 1971.8054567964418, + "y": 207.624530381245 + }, + "dragging": false } ], "edges": [ { - "source": "llmChain_2", - "sourceHandle": "llmChain_2-output-outputPrediction-string", - "target": "promptTemplate_3", - "targetHandle": "promptTemplate_3-input-promptValues-string", + "source": "openAI_2", + "sourceHandle": "openAI_2-output-openAI-OpenAI|BaseLLM|BaseLanguageModel|BaseLangChain", + "target": "llmChain_0", + "targetHandle": "llmChain_0-input-model-BaseLanguageModel", "type": "buttonedge", - "id": "llmChain_2-llmChain_2-output-outputPrediction-string-promptTemplate_3-promptTemplate_3-input-promptValues-string", + "id": "openAI_2-openAI_2-output-openAI-OpenAI|BaseLLM|BaseLanguageModel|BaseLangChain-llmChain_0-llmChain_0-input-model-BaseLanguageModel", "data": { "label": "" } }, { - "source": "openAI_2", - "sourceHandle": "openAI_2-output-openAI-OpenAI|BaseLLM|BaseLanguageModel|BaseLangChain", - "target": "llmChain_2", - "targetHandle": "llmChain_2-input-model-BaseLanguageModel", + "source": "promptTemplate_0", + "sourceHandle": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", + "target": "llmChain_0", + "targetHandle": "llmChain_0-input-prompt-BasePromptTemplate", "type": "buttonedge", - "id": "openAI_2-openAI_2-output-openAI-OpenAI|BaseLLM|BaseLanguageModel|BaseLangChain-llmChain_2-llmChain_2-input-model-BaseLanguageModel", + "id": "promptTemplate_0-promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_0-llmChain_0-input-prompt-BasePromptTemplate", "data": { "label": "" } }, { - "source": "promptTemplate_2", - "sourceHandle": "promptTemplate_2-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "target": "llmChain_2", - "targetHandle": "llmChain_2-input-prompt-BasePromptTemplate", + "source": "llmChain_0", + "sourceHandle": "llmChain_0-output-outputPrediction-string|json", + "target": "promptTemplate_1", + "targetHandle": "promptTemplate_1-input-promptValues-json", "type": "buttonedge", - "id": "promptTemplate_2-promptTemplate_2-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_2-llmChain_2-input-prompt-BasePromptTemplate", + "id": "llmChain_0-llmChain_0-output-outputPrediction-string|json-promptTemplate_1-promptTemplate_1-input-promptValues-json", "data": { "label": "" } @@ -627,21 +623,21 @@ { "source": "openAI_3", "sourceHandle": "openAI_3-output-openAI-OpenAI|BaseLLM|BaseLanguageModel|BaseLangChain", - "target": "llmChain_3", - "targetHandle": "llmChain_3-input-model-BaseLanguageModel", + "target": "llmChain_1", + "targetHandle": "llmChain_1-input-model-BaseLanguageModel", "type": "buttonedge", - "id": "openAI_3-openAI_3-output-openAI-OpenAI|BaseLLM|BaseLanguageModel|BaseLangChain-llmChain_3-llmChain_3-input-model-BaseLanguageModel", + "id": "openAI_3-openAI_3-output-openAI-OpenAI|BaseLLM|BaseLanguageModel|BaseLangChain-llmChain_1-llmChain_1-input-model-BaseLanguageModel", "data": { "label": "" } }, { - "source": "promptTemplate_3", - "sourceHandle": "promptTemplate_3-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "target": "llmChain_3", - "targetHandle": "llmChain_3-input-prompt-BasePromptTemplate", + "source": "promptTemplate_1", + "sourceHandle": "promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", + "target": "llmChain_1", + "targetHandle": "llmChain_1-input-prompt-BasePromptTemplate", "type": "buttonedge", - "id": "promptTemplate_3-promptTemplate_3-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_3-llmChain_3-input-prompt-BasePromptTemplate", + "id": "promptTemplate_1-promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_1-llmChain_1-input-prompt-BasePromptTemplate", "data": { "label": "" } diff --git a/packages/server/marketplaces/Simple LLM Chain.json b/packages/server/marketplaces/Simple LLM Chain.json index c9d354bc067..cc193d5ccff 100644 --- a/packages/server/marketplaces/Simple LLM Chain.json +++ b/packages/server/marketplaces/Simple LLM Chain.json @@ -3,7 +3,7 @@ "nodes": [ { "width": 300, - "height": 526, + "height": 524, "id": "openAI_1", "position": { "x": 510.75932526856377, @@ -156,68 +156,7 @@ }, { "width": 300, - "height": 534, - "id": "promptTemplate_1", - "position": { - "x": 514.5434056794296, - "y": 507.47798128037107 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_1", - "label": "Prompt Template", - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_1-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "string", - "rows": 4, - "placeholder": "{\n \"input_language\": \"English\",\n \"output_language\": \"French\"\n}", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_1-input-promptValues-string" - } - ], - "inputAnchors": [], - "inputs": { - "template": "", - "promptValues": "" - }, - "outputAnchors": [ - { - "id": "promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 514.5434056794296, - "y": 507.47798128037107 - }, - "dragging": false - }, - { - "width": 300, - "height": 407, + "height": 405, "id": "llmChain_1", "position": { "x": 970.9254258940236, @@ -258,7 +197,7 @@ ], "inputs": { "model": "{{openAI_1.data.instance}}", - "prompt": "{{promptTemplate_1.data.instance}}", + "prompt": "{{promptTemplate_0.data.instance}}", "chainName": "" }, "outputAnchors": [ @@ -274,10 +213,10 @@ "type": "LLMChain | BaseChain | BaseLangChain" }, { - "id": "llmChain_1-output-outputPrediction-string", + "id": "llmChain_1-output-outputPrediction-string|json", "name": "outputPrediction", "label": "Output Prediction", - "type": "string" + "type": "string | json" } ], "default": "llmChain" @@ -294,6 +233,65 @@ }, "selected": false, "dragging": false + }, + { + "width": 300, + "height": 475, + "id": "promptTemplate_0", + "position": { + "x": 517.7412884791509, + "y": 506.7411400888471 + }, + "type": "customNode", + "data": { + "id": "promptTemplate_0", + "label": "Prompt Template", + "name": "promptTemplate", + "type": "PromptTemplate", + "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], + "category": "Prompts", + "description": "Schema to represent a basic prompt for an LLM", + "inputParams": [ + { + "label": "Template", + "name": "template", + "type": "string", + "rows": 4, + "placeholder": "What is a good name for a company that makes {product}?", + "id": "promptTemplate_0-input-template-string" + }, + { + "label": "Format Prompt Values", + "name": "promptValues", + "type": "json", + "optional": true, + "acceptVariable": true, + "list": true, + "id": "promptTemplate_0-input-promptValues-json" + } + ], + "inputAnchors": [], + "inputs": { + "template": "What is a good name for a company that makes {product}?", + "promptValues": "" + }, + "outputAnchors": [ + { + "id": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", + "name": "promptTemplate", + "label": "PromptTemplate", + "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" + } + ], + "outputs": {}, + "selected": false + }, + "selected": false, + "positionAbsolute": { + "x": 517.7412884791509, + "y": 506.7411400888471 + }, + "dragging": false } ], "edges": [ @@ -309,12 +307,12 @@ } }, { - "source": "promptTemplate_1", - "sourceHandle": "promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", + "source": "promptTemplate_0", + "sourceHandle": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", "target": "llmChain_1", "targetHandle": "llmChain_1-input-prompt-BasePromptTemplate", "type": "buttonedge", - "id": "promptTemplate_1-promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_1-llmChain_1-input-prompt-BasePromptTemplate", + "id": "promptTemplate_0-promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_1-llmChain_1-input-prompt-BasePromptTemplate", "data": { "label": "" } diff --git a/packages/server/marketplaces/Translator.json b/packages/server/marketplaces/Translator.json index fda400e283a..942bbecdb2e 100644 --- a/packages/server/marketplaces/Translator.json +++ b/packages/server/marketplaces/Translator.json @@ -3,77 +3,7 @@ "nodes": [ { "width": 300, - "height": 711, - "id": "chatPromptTemplate_1", - "position": { - "x": 441.8516979620723, - "y": 636.1108860994266 - }, - "type": "customNode", - "data": { - "id": "chatPromptTemplate_1", - "label": "Chat Prompt Template", - "name": "chatPromptTemplate", - "type": "ChatPromptTemplate", - "baseClasses": ["ChatPromptTemplate", "BaseChatPromptTemplate", "BasePromptTemplate"], - "category": "Prompts", - "description": "Schema to represent a chat prompt", - "inputParams": [ - { - "label": "System Message", - "name": "systemMessagePrompt", - "type": "string", - "rows": 4, - "placeholder": "You are a helpful assistant that translates {input_language} to {output_language}.", - "id": "chatPromptTemplate_1-input-systemMessagePrompt-string" - }, - { - "label": "Human Message", - "name": "humanMessagePrompt", - "type": "string", - "rows": 4, - "placeholder": "{text}", - "id": "chatPromptTemplate_1-input-humanMessagePrompt-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "string", - "rows": 4, - "placeholder": "{\n \"input_language\": \"English\",\n \"output_language\": \"French\"\n}", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "chatPromptTemplate_1-input-promptValues-string" - } - ], - "inputAnchors": [], - "inputs": { - "systemMessagePrompt": "You are a helpful assistant that translates {input_language} to {output_language}.", - "humanMessagePrompt": "{input}", - "promptValues": "{\n \"input_language\": \"English\",\n \"output_language\": \"French\"\n}" - }, - "outputAnchors": [ - { - "id": "chatPromptTemplate_1-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate", - "name": "chatPromptTemplate", - "label": "ChatPromptTemplate", - "type": "ChatPromptTemplate | BaseChatPromptTemplate | BasePromptTemplate" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 441.8516979620723, - "y": 636.1108860994266 - }, - "dragging": false - }, - { - "width": 300, - "height": 526, + "height": 524, "id": "chatOpenAI_1", "position": { "x": 439.5219561593599, @@ -224,7 +154,7 @@ }, { "width": 300, - "height": 407, + "height": 405, "id": "llmChain_1", "position": { "x": 865.7775572410412, @@ -265,7 +195,7 @@ ], "inputs": { "model": "{{chatOpenAI_1.data.instance}}", - "prompt": "{{chatPromptTemplate_1.data.instance}}", + "prompt": "{{chatPromptTemplate_0.data.instance}}", "chainName": "Language Translation" }, "outputAnchors": [ @@ -281,10 +211,10 @@ "type": "LLMChain | BaseChain | BaseLangChain" }, { - "id": "llmChain_1-output-outputPrediction-string", + "id": "llmChain_1-output-outputPrediction-string|json", "name": "outputPrediction", "label": "Output Prediction", - "type": "string" + "type": "string | json" } ], "default": "llmChain" @@ -301,6 +231,74 @@ "y": 543.9211372857111 }, "dragging": false + }, + { + "width": 300, + "height": 652, + "id": "chatPromptTemplate_0", + "position": { + "x": 437.51367850489396, + "y": 649.7619214034173 + }, + "type": "customNode", + "data": { + "id": "chatPromptTemplate_0", + "label": "Chat Prompt Template", + "name": "chatPromptTemplate", + "type": "ChatPromptTemplate", + "baseClasses": ["ChatPromptTemplate", "BaseChatPromptTemplate", "BasePromptTemplate"], + "category": "Prompts", + "description": "Schema to represent a chat prompt", + "inputParams": [ + { + "label": "System Message", + "name": "systemMessagePrompt", + "type": "string", + "rows": 4, + "placeholder": "You are a helpful assistant that translates {input_language} to {output_language}.", + "id": "chatPromptTemplate_0-input-systemMessagePrompt-string" + }, + { + "label": "Human Message", + "name": "humanMessagePrompt", + "type": "string", + "rows": 4, + "placeholder": "{text}", + "id": "chatPromptTemplate_0-input-humanMessagePrompt-string" + }, + { + "label": "Format Prompt Values", + "name": "promptValues", + "type": "json", + "optional": true, + "acceptVariable": true, + "list": true, + "id": "chatPromptTemplate_0-input-promptValues-json" + } + ], + "inputAnchors": [], + "inputs": { + "systemMessagePrompt": "You are a helpful assistant that translates {input_language} to {output_language}.", + "humanMessagePrompt": "{text}", + "promptValues": "{\"input_language\":\"English\",\"output_language\":\"French\",\"text\":\"{{question}}\"}" + }, + "outputAnchors": [ + { + "id": "chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate", + "name": "chatPromptTemplate", + "label": "ChatPromptTemplate", + "type": "ChatPromptTemplate | BaseChatPromptTemplate | BasePromptTemplate" + } + ], + "outputs": {}, + "selected": false + }, + "selected": false, + "positionAbsolute": { + "x": 437.51367850489396, + "y": 649.7619214034173 + }, + "dragging": false } ], "edges": [ @@ -316,12 +314,12 @@ } }, { - "source": "chatPromptTemplate_1", - "sourceHandle": "chatPromptTemplate_1-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate", + "source": "chatPromptTemplate_0", + "sourceHandle": "chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate", "target": "llmChain_1", "targetHandle": "llmChain_1-input-prompt-BasePromptTemplate", "type": "buttonedge", - "id": "chatPromptTemplate_1-chatPromptTemplate_1-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate-llmChain_1-llmChain_1-input-prompt-BasePromptTemplate", + "id": "chatPromptTemplate_0-chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate-llmChain_1-llmChain_1-input-prompt-BasePromptTemplate", "data": { "label": "" } diff --git a/packages/ui/package.json b/packages/ui/package.json index 1e55f1c8a6f..ba1483b4d19 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -18,6 +18,7 @@ "clsx": "^1.1.1", "flowise-embed": "*", "flowise-embed-react": "*", + "flowise-react-json-view": "*", "formik": "^2.2.6", "framer-motion": "^4.1.13", "history": "^5.0.0", @@ -33,7 +34,6 @@ "react-datepicker": "^4.8.0", "react-device-detect": "^1.17.0", "react-dom": "^18.2.0", - "react-json-view": "^1.21.3", "react-markdown": "^8.0.6", "react-perfect-scrollbar": "^1.5.8", "react-redux": "^8.0.5", diff --git a/packages/ui/src/ui-component/dialog/EditPromptValuesDialog.js b/packages/ui/src/ui-component/dialog/EditPromptValuesDialog.js deleted file mode 100644 index 199b130675a..00000000000 --- a/packages/ui/src/ui-component/dialog/EditPromptValuesDialog.js +++ /dev/null @@ -1,256 +0,0 @@ -import { createPortal } from 'react-dom' -import { useState, useEffect } from 'react' -import { useSelector } from 'react-redux' -import PropTypes from 'prop-types' -import { - Button, - Dialog, - DialogActions, - DialogContent, - Box, - List, - ListItemButton, - ListItem, - ListItemAvatar, - ListItemText, - Typography, - Stack -} from '@mui/material' -import { useTheme } from '@mui/material/styles' -import PerfectScrollbar from 'react-perfect-scrollbar' -import { StyledButton } from 'ui-component/button/StyledButton' -import { DarkCodeEditor } from 'ui-component/editor/DarkCodeEditor' -import { LightCodeEditor } from 'ui-component/editor/LightCodeEditor' - -import './EditPromptValuesDialog.css' -import { baseURL } from 'store/constant' - -const EditPromptValuesDialog = ({ show, dialogProps, onCancel, onConfirm }) => { - const portalElement = document.getElementById('portal') - - const theme = useTheme() - const customization = useSelector((state) => state.customization) - const languageType = 'json' - - const [inputValue, setInputValue] = useState('') - const [inputParam, setInputParam] = useState(null) - const [textCursorPosition, setTextCursorPosition] = useState({}) - - useEffect(() => { - if (dialogProps.value) setInputValue(dialogProps.value) - if (dialogProps.inputParam) setInputParam(dialogProps.inputParam) - - return () => { - setInputValue('') - setInputParam(null) - setTextCursorPosition({}) - } - }, [dialogProps]) - - const onMouseUp = (e) => { - if (e.target && e.target.selectionEnd && e.target.value) { - const cursorPosition = e.target.selectionEnd - const textBeforeCursorPosition = e.target.value.substring(0, cursorPosition) - const textAfterCursorPosition = e.target.value.substring(cursorPosition, e.target.value.length) - const body = { - textBeforeCursorPosition, - textAfterCursorPosition - } - setTextCursorPosition(body) - } else { - setTextCursorPosition({}) - } - } - - const onSelectOutputResponseClick = (node, isUserQuestion = false) => { - let variablePath = isUserQuestion ? `question` : `${node.id}.data.instance` - if (textCursorPosition) { - let newInput = '' - if (textCursorPosition.textBeforeCursorPosition === undefined && textCursorPosition.textAfterCursorPosition === undefined) - newInput = `${inputValue}${`{{${variablePath}}}`}` - else newInput = `${textCursorPosition.textBeforeCursorPosition}{{${variablePath}}}${textCursorPosition.textAfterCursorPosition}` - setInputValue(newInput) - } - } - - const component = show ? ( - - -
- {inputParam && inputParam.type === 'string' && ( -
- - {inputParam.label} - - - {customization.isDarkMode ? ( - setInputValue(code)} - placeholder={inputParam.placeholder} - type={languageType} - onMouseUp={(e) => onMouseUp(e)} - onBlur={(e) => onMouseUp(e)} - style={{ - fontSize: '0.875rem', - minHeight: 'calc(100vh - 220px)', - width: '100%' - }} - /> - ) : ( - setInputValue(code)} - placeholder={inputParam.placeholder} - type={languageType} - onMouseUp={(e) => onMouseUp(e)} - onBlur={(e) => onMouseUp(e)} - style={{ - fontSize: '0.875rem', - minHeight: 'calc(100vh - 220px)', - width: '100%' - }} - /> - )} - -
- )} - {!dialogProps.disabled && inputParam && inputParam.acceptVariable && ( -
- - Select Variable - - - - - onSelectOutputResponseClick(null, true)} - > - - -
- AI -
-
- -
-
- {dialogProps.availableNodesForVariable && - dialogProps.availableNodesForVariable.length > 0 && - dialogProps.availableNodesForVariable.map((node, index) => { - const selectedOutputAnchor = node.data.outputAnchors[0].options.find( - (ancr) => ancr.name === node.data.outputs['output'] - ) - return ( - onSelectOutputResponseClick(node)} - > - - -
- {node.data.name} -
-
- -
-
- ) - })} -
-
-
-
- )} -
-
- - - onConfirm(inputValue, inputParam.name)}> - {dialogProps.confirmButtonName} - - -
- ) : null - - return createPortal(component, portalElement) -} - -EditPromptValuesDialog.propTypes = { - show: PropTypes.bool, - dialogProps: PropTypes.object, - onCancel: PropTypes.func, - onConfirm: PropTypes.func -} - -export default EditPromptValuesDialog diff --git a/packages/ui/src/ui-component/dialog/EditPromptValuesDialog.css b/packages/ui/src/ui-component/dialog/ExpandTextDialog.css similarity index 100% rename from packages/ui/src/ui-component/dialog/EditPromptValuesDialog.css rename to packages/ui/src/ui-component/dialog/ExpandTextDialog.css diff --git a/packages/ui/src/ui-component/dialog/ExpandTextDialog.js b/packages/ui/src/ui-component/dialog/ExpandTextDialog.js new file mode 100644 index 00000000000..b955ccdb87a --- /dev/null +++ b/packages/ui/src/ui-component/dialog/ExpandTextDialog.js @@ -0,0 +1,105 @@ +import { createPortal } from 'react-dom' +import { useState, useEffect } from 'react' +import { useSelector } from 'react-redux' +import PropTypes from 'prop-types' +import { Button, Dialog, DialogActions, DialogContent, Typography } from '@mui/material' +import { useTheme } from '@mui/material/styles' +import PerfectScrollbar from 'react-perfect-scrollbar' +import { StyledButton } from 'ui-component/button/StyledButton' +import { DarkCodeEditor } from 'ui-component/editor/DarkCodeEditor' +import { LightCodeEditor } from 'ui-component/editor/LightCodeEditor' + +import './ExpandTextDialog.css' + +const ExpandTextDialog = ({ show, dialogProps, onCancel, onConfirm }) => { + const portalElement = document.getElementById('portal') + + const theme = useTheme() + const customization = useSelector((state) => state.customization) + const languageType = 'json' + + const [inputValue, setInputValue] = useState('') + const [inputParam, setInputParam] = useState(null) + + useEffect(() => { + if (dialogProps.value) setInputValue(dialogProps.value) + if (dialogProps.inputParam) setInputParam(dialogProps.inputParam) + + return () => { + setInputValue('') + setInputParam(null) + } + }, [dialogProps]) + + const component = show ? ( + + +
+ {inputParam && inputParam.type === 'string' && ( +
+ + {inputParam.label} + + + {customization.isDarkMode ? ( + setInputValue(code)} + placeholder={inputParam.placeholder} + type={languageType} + style={{ + fontSize: '0.875rem', + minHeight: 'calc(100vh - 220px)', + width: '100%' + }} + /> + ) : ( + setInputValue(code)} + placeholder={inputParam.placeholder} + type={languageType} + style={{ + fontSize: '0.875rem', + minHeight: 'calc(100vh - 220px)', + width: '100%' + }} + /> + )} + +
+ )} +
+
+ + + onConfirm(inputValue, inputParam.name)}> + {dialogProps.confirmButtonName} + + +
+ ) : null + + return createPortal(component, portalElement) +} + +ExpandTextDialog.propTypes = { + show: PropTypes.bool, + dialogProps: PropTypes.object, + onCancel: PropTypes.func, + onConfirm: PropTypes.func +} + +export default ExpandTextDialog diff --git a/packages/ui/src/ui-component/dialog/FormatPromptValuesDialog.js b/packages/ui/src/ui-component/dialog/FormatPromptValuesDialog.js new file mode 100644 index 00000000000..df1d357edc8 --- /dev/null +++ b/packages/ui/src/ui-component/dialog/FormatPromptValuesDialog.js @@ -0,0 +1,56 @@ +import { createPortal } from 'react-dom' +import { useSelector } from 'react-redux' +import PropTypes from 'prop-types' +import { Dialog, DialogContent, DialogTitle } from '@mui/material' +import PerfectScrollbar from 'react-perfect-scrollbar' +import { JsonEditorInput } from 'ui-component/json/JsonEditor' + +const FormatPromptValuesDialog = ({ show, dialogProps, onChange, onCancel }) => { + const portalElement = document.getElementById('portal') + const customization = useSelector((state) => state.customization) + + const component = show ? ( + + + Format Prompt Values + + + + onChange(newValue)} + value={dialogProps.value} + isDarkMode={customization.isDarkMode} + inputParam={dialogProps.inputParam} + nodes={dialogProps.nodes} + edges={dialogProps.edges} + nodeId={dialogProps.nodeId} + /> + + + + ) : null + + return createPortal(component, portalElement) +} + +FormatPromptValuesDialog.propTypes = { + show: PropTypes.bool, + dialogProps: PropTypes.object, + onChange: PropTypes.func, + onCancel: PropTypes.func +} + +export default FormatPromptValuesDialog diff --git a/packages/ui/src/ui-component/dialog/SourceDocDialog.js b/packages/ui/src/ui-component/dialog/SourceDocDialog.js index a088a6c49e8..6bf8692fbce 100644 --- a/packages/ui/src/ui-component/dialog/SourceDocDialog.js +++ b/packages/ui/src/ui-component/dialog/SourceDocDialog.js @@ -3,7 +3,7 @@ import { useState, useEffect } from 'react' import { useSelector } from 'react-redux' import PropTypes from 'prop-types' import { Dialog, DialogContent, DialogTitle } from '@mui/material' -import ReactJson from 'react-json-view' +import ReactJson from 'flowise-react-json-view' const SourceDocDialog = ({ show, dialogProps, onCancel }) => { const portalElement = document.getElementById('portal') diff --git a/packages/ui/src/ui-component/input/Input.js b/packages/ui/src/ui-component/input/Input.js index 7f0e0610e7e..e7744764162 100644 --- a/packages/ui/src/ui-component/input/Input.js +++ b/packages/ui/src/ui-component/input/Input.js @@ -1,7 +1,7 @@ import { useState } from 'react' import PropTypes from 'prop-types' import { FormControl, OutlinedInput } from '@mui/material' -import EditPromptValuesDialog from 'ui-component/dialog/EditPromptValuesDialog' +import ExpandTextDialog from 'ui-component/dialog/ExpandTextDialog' export const Input = ({ inputParam, value, onChange, disabled = false, showDialog, dialogProps, onDialogCancel, onDialogConfirm }) => { const [myValue, setMyValue] = useState(value ?? '') @@ -45,7 +45,7 @@ export const Input = ({ inputParam, value, onChange, disabled = false, showDialo /> {showDialog && ( - + > )} ) diff --git a/packages/ui/src/ui-component/json/JsonEditor.js b/packages/ui/src/ui-component/json/JsonEditor.js index 06442df27c2..4bf8f306ddd 100644 --- a/packages/ui/src/ui-component/json/JsonEditor.js +++ b/packages/ui/src/ui-component/json/JsonEditor.js @@ -1,10 +1,32 @@ -import { useState } from 'react' +import { useEffect, useState } from 'react' import PropTypes from 'prop-types' -import { FormControl } from '@mui/material' -import ReactJson from 'react-json-view' +import { FormControl, Popover } from '@mui/material' +import ReactJson from 'flowise-react-json-view' +import SelectVariable from './SelectVariable' +import { cloneDeep } from 'lodash' +import { getAvailableNodesForVariable } from 'utils/genericHelper' -export const JsonEditorInput = ({ value, onChange, disabled = false, isDarkMode = false }) => { +export const JsonEditorInput = ({ value, onChange, inputParam, nodes, edges, nodeId, disabled = false, isDarkMode = false }) => { const [myValue, setMyValue] = useState(value ? JSON.parse(value) : {}) + const [availableNodesForVariable, setAvailableNodesForVariable] = useState([]) + const [mouseUpKey, setMouseUpKey] = useState('') + + const [anchorEl, setAnchorEl] = useState(null) + const openPopOver = Boolean(anchorEl) + + const handleClosePopOver = () => { + setAnchorEl(null) + } + + const setNewVal = (val) => { + const newVal = cloneDeep(myValue) + newVal[mouseUpKey] = val + onChange(JSON.stringify(newVal)) + setMyValue((params) => ({ + ...params, + [mouseUpKey]: val + })) + } const onClipboardCopy = (e) => { const src = e.src @@ -15,6 +37,13 @@ export const JsonEditorInput = ({ value, onChange, disabled = false, isDarkMode } } + useEffect(() => { + if (!disabled && nodes && edges && nodeId && inputParam) { + const nodesForVariable = inputParam?.acceptVariable ? getAvailableNodesForVariable(nodes, edges, nodeId, inputParam.id) : [] + setAvailableNodesForVariable(nodesForVariable) + } + }, [disabled, inputParam, nodes, edges, nodeId]) + return ( <> @@ -30,28 +59,60 @@ export const JsonEditorInput = ({ value, onChange, disabled = false, isDarkMode /> )} {!disabled && ( - onClipboardCopy(e)} - onEdit={(edit) => { - setMyValue(edit.updated_src) - onChange(JSON.stringify(edit.updated_src)) - }} - onAdd={() => { - //console.log(add) - }} - onDelete={(deleteobj) => { - setMyValue(deleteobj.updated_src) - onChange(JSON.stringify(deleteobj.updated_src)) - }} - /> +
+ onClipboardCopy(e)} + onMouseUp={(event) => { + if (inputParam?.acceptVariable) { + setMouseUpKey(event.name) + setAnchorEl(event.currentTarget) + } + }} + onEdit={(edit) => { + setMyValue(edit.updated_src) + onChange(JSON.stringify(edit.updated_src)) + }} + onAdd={() => { + //console.log(add) + }} + onDelete={(deleteobj) => { + setMyValue(deleteobj.updated_src) + onChange(JSON.stringify(deleteobj.updated_src)) + }} + /> +
)}
+ {inputParam?.acceptVariable && ( + + { + setNewVal(val) + handleClosePopOver() + }} + /> + + )} ) } @@ -60,5 +121,9 @@ JsonEditorInput.propTypes = { value: PropTypes.string, onChange: PropTypes.func, disabled: PropTypes.bool, - isDarkMode: PropTypes.bool + isDarkMode: PropTypes.bool, + inputParam: PropTypes.object, + nodes: PropTypes.array, + edges: PropTypes.array, + nodeId: PropTypes.string } diff --git a/packages/ui/src/ui-component/json/SelectVariable.js b/packages/ui/src/ui-component/json/SelectVariable.js new file mode 100644 index 00000000000..1b891ed116f --- /dev/null +++ b/packages/ui/src/ui-component/json/SelectVariable.js @@ -0,0 +1,126 @@ +import { useSelector } from 'react-redux' +import PropTypes from 'prop-types' +import { Box, List, ListItemButton, ListItem, ListItemAvatar, ListItemText, Typography, Stack } from '@mui/material' +import PerfectScrollbar from 'react-perfect-scrollbar' + +import { baseURL } from 'store/constant' + +const SelectVariable = ({ availableNodesForVariable, disabled = false, onSelectAndReturnVal }) => { + const customization = useSelector((state) => state.customization) + + const onSelectOutputResponseClick = (node, isUserQuestion = false) => { + let variablePath = isUserQuestion ? `question` : `${node.id}.data.instance` + const newInput = `{{${variablePath}}}` + onSelectAndReturnVal(newInput) + } + + return ( + <> + {!disabled && ( +
+ + Select Variable + + + + + onSelectOutputResponseClick(null, true)} + > + + +
+ AI +
+
+ +
+
+ {availableNodesForVariable && + availableNodesForVariable.length > 0 && + availableNodesForVariable.map((node, index) => { + const selectedOutputAnchor = node.data.outputAnchors[0].options.find( + (ancr) => ancr.name === node.data.outputs['output'] + ) + return ( + onSelectOutputResponseClick(node)} + > + + +
+ {node.data.name} +
+
+ +
+
+ ) + })} +
+
+
+
+ )} + + ) +} + +SelectVariable.propTypes = { + availableNodesForVariable: PropTypes.array, + disabled: PropTypes.bool, + onSelectAndReturnVal: PropTypes.func +} + +export default SelectVariable diff --git a/packages/ui/src/utils/genericHelper.js b/packages/ui/src/utils/genericHelper.js index 03f891ec282..42a63057538 100644 --- a/packages/ui/src/utils/genericHelper.js +++ b/packages/ui/src/utils/genericHelper.js @@ -285,7 +285,7 @@ export const generateExportFlowData = (flowData) => { } export const getAvailableNodesForVariable = (nodes, edges, target, targetHandle) => { - // example edge id = "llmChain_0-llmChain_0-output-outputPrediction-string-llmChain_1-llmChain_1-input-promptValues-string" + // example edge id = "llmChain_0-llmChain_0-output-outputPrediction-string|json-llmChain_1-llmChain_1-input-promptValues-string" // {source} -{sourceHandle} -{target} -{targetHandle} const parentNodes = [] const inputEdges = edges.filter((edg) => edg.target === target && edg.targetHandle === targetHandle) @@ -353,3 +353,31 @@ export const generateRandomGradient = () => { return gradient } + +export const getInputVariables = (paramValue) => { + let returnVal = paramValue + const variableStack = [] + const inputVariables = [] + let startIdx = 0 + const endIdx = returnVal.length + + while (startIdx < endIdx) { + const substr = returnVal.substring(startIdx, startIdx + 1) + + // Store the opening double curly bracket + if (substr === '{') { + variableStack.push({ substr, startIdx: startIdx + 1 }) + } + + // Found the complete variable + if (substr === '}' && variableStack.length > 0 && variableStack[variableStack.length - 1].substr === '{') { + const variableStartIdx = variableStack[variableStack.length - 1].startIdx + const variableEndIdx = startIdx + const variableFullPath = returnVal.substring(variableStartIdx, variableEndIdx) + inputVariables.push(variableFullPath) + variableStack.pop() + } + startIdx += 1 + } + return inputVariables +} diff --git a/packages/ui/src/views/canvas/NodeInputHandler.js b/packages/ui/src/views/canvas/NodeInputHandler.js index 4ad2190422b..2d96bcb582c 100644 --- a/packages/ui/src/views/canvas/NodeInputHandler.js +++ b/packages/ui/src/views/canvas/NodeInputHandler.js @@ -5,7 +5,7 @@ import { useSelector } from 'react-redux' // material-ui import { useTheme, styled } from '@mui/material/styles' -import { Box, Typography, Tooltip, IconButton } from '@mui/material' +import { Box, Typography, Tooltip, IconButton, Button } from '@mui/material' import { tooltipClasses } from '@mui/material/Tooltip' import { IconArrowsMaximize, IconEdit } from '@tabler/icons' @@ -16,10 +16,13 @@ import { Input } from 'ui-component/input/Input' import { File } from 'ui-component/file/File' import { SwitchInput } from 'ui-component/switch/Switch' import { flowContext } from 'store/context/ReactFlowContext' -import { isValidConnection, getAvailableNodesForVariable } from 'utils/genericHelper' +import { isValidConnection } from 'utils/genericHelper' import { JsonEditorInput } from 'ui-component/json/JsonEditor' import { TooltipWithParser } from 'ui-component/tooltip/TooltipWithParser' import ToolDialog from 'views/tools/ToolDialog' +import FormatPromptValuesDialog from 'ui-component/dialog/FormatPromptValuesDialog' + +import { getInputVariables } from 'utils/genericHelper' const EDITABLE_TOOLS = ['selectedTool'] @@ -43,6 +46,8 @@ const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false, isA const [showAsyncOptionDialog, setAsyncOptionEditDialog] = useState('') const [asyncOptionEditDialogProps, setAsyncOptionEditDialogProps] = useState({}) const [reloadTimestamp, setReloadTimestamp] = useState(Date.now().toString()) + const [showFormatPromptValuesDialog, setShowFormatPromptValuesDialog] = useState(false) + const [formatPromptValuesDialogProps, setFormatPromptValuesDialogProps] = useState({}) const onExpandDialogClicked = (value, inputParam) => { const dialogProp = { @@ -52,17 +57,34 @@ const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false, isA confirmButtonName: 'Save', cancelButtonName: 'Cancel' } - - if (!disabled) { - const nodes = reactFlowInstance.getNodes() - const edges = reactFlowInstance.getEdges() - const nodesForVariable = inputParam.acceptVariable ? getAvailableNodesForVariable(nodes, edges, data.id, inputParam.id) : [] - dialogProp.availableNodesForVariable = nodesForVariable - } setExpandDialogProps(dialogProp) setShowExpandDialog(true) } + const onFormatPromptValuesClicked = (value, inputParam) => { + // Preset values if the field is format prompt values + let inputValue = value + if (inputParam.name === 'promptValues' && !value) { + const obj = {} + const templateValue = + (data.inputs['template'] ?? '') + (data.inputs['systemMessagePrompt'] ?? '') + (data.inputs['humanMessagePrompt'] ?? '') + const inputVariables = getInputVariables(templateValue) + for (const inputVariable of inputVariables) { + obj[inputVariable] = '' + } + if (Object.keys(obj).length) inputValue = JSON.stringify(obj) + } + const dialogProp = { + value: inputValue, + inputParam, + nodes: reactFlowInstance.getNodes(), + edges: reactFlowInstance.getEdges(), + nodeId: data.id + } + setFormatPromptValuesDialogProps(dialogProp) + setShowFormatPromptValuesDialog(true) + } + const onExpandDialogSave = (newValue, inputParamName) => { setShowExpandDialog(false) data.inputs[inputParamName] = newValue @@ -217,12 +239,33 @@ const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false, isA /> )} {inputParam.type === 'json' && ( - (data.inputs[inputParam.name] = newValue)} - value={data.inputs[inputParam.name] ?? inputParam.default ?? ''} - isDarkMode={customization.isDarkMode} - /> + <> + {!inputParam?.acceptVariable && ( + (data.inputs[inputParam.name] = newValue)} + value={data.inputs[inputParam.name] ?? inputParam.default ?? ''} + isDarkMode={customization.isDarkMode} + /> + )} + {inputParam?.acceptVariable && ( + <> + + setShowFormatPromptValuesDialog(false)} + onChange={(newValue) => (data.inputs[inputParam.name] = newValue)} + > + + )} + )} {inputParam.type === 'options' && (