format prompt values revamp

pull/440/head
Henry 2023-06-28 22:59:56 +01:00
parent dc2f35bfad
commit 511c4995e9
20 changed files with 1014 additions and 910 deletions

View File

@ -50,7 +50,7 @@ class LLMChain_Chains implements INode {
{
label: 'Output Prediction',
name: 'outputPrediction',
baseClasses: ['string']
baseClasses: ['string', 'json']
}
]
}

View File

@ -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

View File

@ -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

View File

@ -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',

View File

@ -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": ""
}
}
]
}

View File

@ -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,20 +184,68 @@
"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",
"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",
"data": {
"label": ""
}
},
{
"source": "huggingFaceInference_LLMs_0",
"sourceHandle": "huggingFaceInference_LLMs_0-output-huggingFaceInference_LLMs-HuggingFaceInference|LLM|BaseLLM|BaseLanguageModel|BaseLangChain",
@ -269,6 +256,17 @@
"data": {
"label": ""
}
},
{
"source": "promptTemplate_0",
"sourceHandle": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate",
"target": "llmChain_1",
"targetHandle": "llmChain_1-input-prompt-BasePromptTemplate",
"type": "buttonedge",
"id": "promptTemplate_0-promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_1-llmChain_1-input-prompt-BasePromptTemplate",
"data": {
"label": ""
}
}
]
}

View File

@ -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": 407,
"id": "llmChain_3",
"height": 475,
"id": "promptTemplate_0",
"position": {
"x": 1972.2671768945252,
"y": 142.73435419451476
"x": 792.9464838535649,
"y": 527.1718536712464
},
"type": "customNode",
"data": {
"id": "llmChain_3",
"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": 405,
"id": "llmChain_0",
"position": {
"x": 1221.1346231272787,
"y": 538.9546839784628
},
"type": "customNode",
"data": {
"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",
"type": "buttonedge",
"id": "llmChain_2-llmChain_2-output-outputPrediction-string-promptTemplate_3-promptTemplate_3-input-promptValues-string",
"data": {
"label": ""
}
},
{
"source": "openAI_2",
"sourceHandle": "openAI_2-output-openAI-OpenAI|BaseLLM|BaseLanguageModel|BaseLangChain",
"target": "llmChain_2",
"targetHandle": "llmChain_2-input-model-BaseLanguageModel",
"target": "llmChain_0",
"targetHandle": "llmChain_0-input-model-BaseLanguageModel",
"type": "buttonedge",
"id": "openAI_2-openAI_2-output-openAI-OpenAI|BaseLLM|BaseLanguageModel|BaseLangChain-llmChain_2-llmChain_2-input-model-BaseLanguageModel",
"id": "openAI_2-openAI_2-output-openAI-OpenAI|BaseLLM|BaseLanguageModel|BaseLangChain-llmChain_0-llmChain_0-input-model-BaseLanguageModel",
"data": {
"label": ""
}
},
{
"source": "promptTemplate_2",
"sourceHandle": "promptTemplate_2-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate",
"target": "llmChain_2",
"targetHandle": "llmChain_2-input-prompt-BasePromptTemplate",
"source": "promptTemplate_0",
"sourceHandle": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate",
"target": "llmChain_0",
"targetHandle": "llmChain_0-input-prompt-BasePromptTemplate",
"type": "buttonedge",
"id": "promptTemplate_2-promptTemplate_2-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_2-llmChain_2-input-prompt-BasePromptTemplate",
"id": "promptTemplate_0-promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_0-llmChain_0-input-prompt-BasePromptTemplate",
"data": {
"label": ""
}
},
{
"source": "llmChain_0",
"sourceHandle": "llmChain_0-output-outputPrediction-string|json",
"target": "promptTemplate_1",
"targetHandle": "promptTemplate_1-input-promptValues-json",
"type": "buttonedge",
"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": ""
}

View File

@ -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": ""
}

View File

@ -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": ""
}

View File

@ -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",

View File

@ -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 ? (
<Dialog open={show} fullWidth maxWidth='md' aria-labelledby='alert-dialog-title' aria-describedby='alert-dialog-description'>
<DialogContent>
<div style={{ display: 'flex', flexDirection: 'row' }}>
{inputParam && inputParam.type === 'string' && (
<div style={{ flex: 70 }}>
<Typography sx={{ mb: 2, ml: 1 }} variant='h4'>
{inputParam.label}
</Typography>
<PerfectScrollbar
style={{
border: '1px solid',
borderColor: theme.palette.grey['500'],
borderRadius: '12px',
height: '100%',
maxHeight: 'calc(100vh - 220px)',
overflowX: 'hidden',
backgroundColor: 'white'
}}
>
{customization.isDarkMode ? (
<DarkCodeEditor
disabled={dialogProps.disabled}
value={inputValue}
onValueChange={(code) => 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%'
}}
/>
) : (
<LightCodeEditor
disabled={dialogProps.disabled}
value={inputValue}
onValueChange={(code) => 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%'
}}
/>
)}
</PerfectScrollbar>
</div>
)}
{!dialogProps.disabled && inputParam && inputParam.acceptVariable && (
<div style={{ flex: 30 }}>
<Stack flexDirection='row' sx={{ mb: 1, ml: 2 }}>
<Typography variant='h4'>Select Variable</Typography>
</Stack>
<PerfectScrollbar style={{ height: '100%', maxHeight: 'calc(100vh - 220px)', overflowX: 'hidden' }}>
<Box sx={{ pl: 2, pr: 2 }}>
<List>
<ListItemButton
sx={{
p: 0,
borderRadius: `${customization.borderRadius}px`,
boxShadow: '0 2px 14px 0 rgb(32 40 45 / 8%)',
mb: 1
}}
disabled={dialogProps.disabled}
onClick={() => onSelectOutputResponseClick(null, true)}
>
<ListItem alignItems='center'>
<ListItemAvatar>
<div
style={{
width: 50,
height: 50,
borderRadius: '50%',
backgroundColor: 'white'
}}
>
<img
style={{
width: '100%',
height: '100%',
padding: 10,
objectFit: 'contain'
}}
alt='AI'
src='https://raw.githubusercontent.com/zahidkhawaja/langchain-chat-nextjs/main/public/parroticon.png'
/>
</div>
</ListItemAvatar>
<ListItemText
sx={{ ml: 1 }}
primary='question'
secondary={`User's question from chatbox`}
/>
</ListItem>
</ListItemButton>
{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 (
<ListItemButton
key={index}
sx={{
p: 0,
borderRadius: `${customization.borderRadius}px`,
boxShadow: '0 2px 14px 0 rgb(32 40 45 / 8%)',
mb: 1
}}
disabled={dialogProps.disabled}
onClick={() => onSelectOutputResponseClick(node)}
>
<ListItem alignItems='center'>
<ListItemAvatar>
<div
style={{
width: 50,
height: 50,
borderRadius: '50%',
backgroundColor: 'white'
}}
>
<img
style={{
width: '100%',
height: '100%',
padding: 10,
objectFit: 'contain'
}}
alt={node.data.name}
src={`${baseURL}/api/v1/node-icon/${node.data.name}`}
/>
</div>
</ListItemAvatar>
<ListItemText
sx={{ ml: 1 }}
primary={
node.data.inputs.chainName ? node.data.inputs.chainName : node.data.id
}
secondary={`${selectedOutputAnchor?.label ?? 'output'} from ${
node.data.label
}`}
/>
</ListItem>
</ListItemButton>
)
})}
</List>
</Box>
</PerfectScrollbar>
</div>
)}
</div>
</DialogContent>
<DialogActions>
<Button onClick={onCancel}>{dialogProps.cancelButtonName}</Button>
<StyledButton disabled={dialogProps.disabled} variant='contained' onClick={() => onConfirm(inputValue, inputParam.name)}>
{dialogProps.confirmButtonName}
</StyledButton>
</DialogActions>
</Dialog>
) : null
return createPortal(component, portalElement)
}
EditPromptValuesDialog.propTypes = {
show: PropTypes.bool,
dialogProps: PropTypes.object,
onCancel: PropTypes.func,
onConfirm: PropTypes.func
}
export default EditPromptValuesDialog

View File

@ -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 ? (
<Dialog open={show} fullWidth maxWidth='md' aria-labelledby='alert-dialog-title' aria-describedby='alert-dialog-description'>
<DialogContent>
<div style={{ display: 'flex', flexDirection: 'row' }}>
{inputParam && inputParam.type === 'string' && (
<div style={{ flex: 70 }}>
<Typography sx={{ mb: 2, ml: 1 }} variant='h4'>
{inputParam.label}
</Typography>
<PerfectScrollbar
style={{
border: '1px solid',
borderColor: theme.palette.grey['500'],
borderRadius: '12px',
height: '100%',
maxHeight: 'calc(100vh - 220px)',
overflowX: 'hidden',
backgroundColor: 'white'
}}
>
{customization.isDarkMode ? (
<DarkCodeEditor
disabled={dialogProps.disabled}
value={inputValue}
onValueChange={(code) => setInputValue(code)}
placeholder={inputParam.placeholder}
type={languageType}
style={{
fontSize: '0.875rem',
minHeight: 'calc(100vh - 220px)',
width: '100%'
}}
/>
) : (
<LightCodeEditor
disabled={dialogProps.disabled}
value={inputValue}
onValueChange={(code) => setInputValue(code)}
placeholder={inputParam.placeholder}
type={languageType}
style={{
fontSize: '0.875rem',
minHeight: 'calc(100vh - 220px)',
width: '100%'
}}
/>
)}
</PerfectScrollbar>
</div>
)}
</div>
</DialogContent>
<DialogActions>
<Button onClick={onCancel}>{dialogProps.cancelButtonName}</Button>
<StyledButton disabled={dialogProps.disabled} variant='contained' onClick={() => onConfirm(inputValue, inputParam.name)}>
{dialogProps.confirmButtonName}
</StyledButton>
</DialogActions>
</Dialog>
) : null
return createPortal(component, portalElement)
}
ExpandTextDialog.propTypes = {
show: PropTypes.bool,
dialogProps: PropTypes.object,
onCancel: PropTypes.func,
onConfirm: PropTypes.func
}
export default ExpandTextDialog

View File

@ -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 ? (
<Dialog
onClose={onCancel}
open={show}
fullWidth
maxWidth='sm'
aria-labelledby='alert-dialog-title'
aria-describedby='alert-dialog-description'
>
<DialogTitle sx={{ fontSize: '1rem' }} id='alert-dialog-title'>
Format Prompt Values
</DialogTitle>
<DialogContent>
<PerfectScrollbar
style={{
height: '100%',
maxHeight: 'calc(100vh - 220px)',
overflowX: 'hidden'
}}
>
<JsonEditorInput
onChange={(newValue) => onChange(newValue)}
value={dialogProps.value}
isDarkMode={customization.isDarkMode}
inputParam={dialogProps.inputParam}
nodes={dialogProps.nodes}
edges={dialogProps.edges}
nodeId={dialogProps.nodeId}
/>
</PerfectScrollbar>
</DialogContent>
</Dialog>
) : null
return createPortal(component, portalElement)
}
FormatPromptValuesDialog.propTypes = {
show: PropTypes.bool,
dialogProps: PropTypes.object,
onChange: PropTypes.func,
onCancel: PropTypes.func
}
export default FormatPromptValuesDialog

View File

@ -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')

View File

@ -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
/>
</FormControl>
{showDialog && (
<EditPromptValuesDialog
<ExpandTextDialog
show={showDialog}
dialogProps={dialogProps}
onCancel={onDialogCancel}
@ -53,7 +53,7 @@ export const Input = ({ inputParam, value, onChange, disabled = false, showDialo
setMyValue(newValue)
onDialogConfirm(newValue, inputParamName)
}}
></EditPromptValuesDialog>
></ExpandTextDialog>
)}
</>
)

View File

@ -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 (
<>
<FormControl sx={{ mt: 1, width: '100%' }} size='small'>
@ -30,28 +59,60 @@ export const JsonEditorInput = ({ value, onChange, disabled = false, isDarkMode
/>
)}
{!disabled && (
<ReactJson
theme={isDarkMode ? 'ocean' : 'rjv-default'}
style={{ padding: 10, borderRadius: 10 }}
src={myValue}
name={null}
quotesOnKeys={false}
displayDataTypes={false}
enableClipboard={(e) => 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))
}}
/>
<div key={JSON.stringify(myValue)}>
<ReactJson
theme={isDarkMode ? 'ocean' : 'rjv-default'}
style={{ padding: 10, borderRadius: 10 }}
src={myValue}
name={null}
quotesOnKeys={false}
displayDataTypes={false}
enableClipboard={(e) => 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))
}}
/>
</div>
)}
</FormControl>
{inputParam?.acceptVariable && (
<Popover
open={openPopOver}
anchorEl={anchorEl}
onClose={handleClosePopOver}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left'
}}
transformOrigin={{
vertical: 'top',
horizontal: 'left'
}}
>
<SelectVariable
disabled={disabled}
availableNodesForVariable={availableNodesForVariable}
onSelectAndReturnVal={(val) => {
setNewVal(val)
handleClosePopOver()
}}
/>
</Popover>
)}
</>
)
}
@ -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
}

View File

@ -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 && (
<div style={{ flex: 30 }}>
<Stack flexDirection='row' sx={{ mb: 1, ml: 2, mt: 2 }}>
<Typography variant='h5'>Select Variable</Typography>
</Stack>
<PerfectScrollbar style={{ height: '100%', maxHeight: 'calc(100vh - 220px)', overflowX: 'hidden' }}>
<Box sx={{ pl: 2, pr: 2 }}>
<List>
<ListItemButton
sx={{
p: 0,
borderRadius: `${customization.borderRadius}px`,
boxShadow: '0 2px 14px 0 rgb(32 40 45 / 8%)',
mb: 1
}}
disabled={disabled}
onClick={() => onSelectOutputResponseClick(null, true)}
>
<ListItem alignItems='center'>
<ListItemAvatar>
<div
style={{
width: 50,
height: 50,
borderRadius: '50%',
backgroundColor: 'white'
}}
>
<img
style={{
width: '100%',
height: '100%',
padding: 10,
objectFit: 'contain'
}}
alt='AI'
src='https://raw.githubusercontent.com/zahidkhawaja/langchain-chat-nextjs/main/public/parroticon.png'
/>
</div>
</ListItemAvatar>
<ListItemText sx={{ ml: 1 }} primary='question' secondary={`User's question from chatbox`} />
</ListItem>
</ListItemButton>
{availableNodesForVariable &&
availableNodesForVariable.length > 0 &&
availableNodesForVariable.map((node, index) => {
const selectedOutputAnchor = node.data.outputAnchors[0].options.find(
(ancr) => ancr.name === node.data.outputs['output']
)
return (
<ListItemButton
key={index}
sx={{
p: 0,
borderRadius: `${customization.borderRadius}px`,
boxShadow: '0 2px 14px 0 rgb(32 40 45 / 8%)',
mb: 1
}}
disabled={disabled}
onClick={() => onSelectOutputResponseClick(node)}
>
<ListItem alignItems='center'>
<ListItemAvatar>
<div
style={{
width: 50,
height: 50,
borderRadius: '50%',
backgroundColor: 'white'
}}
>
<img
style={{
width: '100%',
height: '100%',
padding: 10,
objectFit: 'contain'
}}
alt={node.data.name}
src={`${baseURL}/api/v1/node-icon/${node.data.name}`}
/>
</div>
</ListItemAvatar>
<ListItemText
sx={{ ml: 1 }}
primary={node.data.inputs.chainName ? node.data.inputs.chainName : node.data.id}
secondary={`${selectedOutputAnchor?.label ?? 'output'} from ${node.data.label}`}
/>
</ListItem>
</ListItemButton>
)
})}
</List>
</Box>
</PerfectScrollbar>
</div>
)}
</>
)
}
SelectVariable.propTypes = {
availableNodesForVariable: PropTypes.array,
disabled: PropTypes.bool,
onSelectAndReturnVal: PropTypes.func
}
export default SelectVariable

View File

@ -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
}

View File

@ -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' && (
<JsonEditorInput
disabled={disabled}
onChange={(newValue) => (data.inputs[inputParam.name] = newValue)}
value={data.inputs[inputParam.name] ?? inputParam.default ?? ''}
isDarkMode={customization.isDarkMode}
/>
<>
{!inputParam?.acceptVariable && (
<JsonEditorInput
disabled={disabled}
onChange={(newValue) => (data.inputs[inputParam.name] = newValue)}
value={data.inputs[inputParam.name] ?? inputParam.default ?? ''}
isDarkMode={customization.isDarkMode}
/>
)}
{inputParam?.acceptVariable && (
<>
<Button
sx={{ borderRadius: 25, width: '100%', mb: 2, mt: 2 }}
variant='outlined'
onClick={() => onFormatPromptValuesClicked(data.inputs[inputParam.name] ?? '', inputParam)}
>
Format Prompt Values
</Button>
<FormatPromptValuesDialog
show={showFormatPromptValuesDialog}
dialogProps={formatPromptValuesDialogProps}
onCancel={() => setShowFormatPromptValuesDialog(false)}
onChange={(newValue) => (data.inputs[inputParam.name] = newValue)}
></FormatPromptValuesDialog>
</>
)}
</>
)}
{inputParam.type === 'options' && (
<Dropdown