diff --git a/packages/components/nodes/agents/ConversationalAgent/ConversationalAgent.ts b/packages/components/nodes/agents/ConversationalAgent/ConversationalAgent.ts index 3641f0bd7..59c589783 100644 --- a/packages/components/nodes/agents/ConversationalAgent/ConversationalAgent.ts +++ b/packages/components/nodes/agents/ConversationalAgent/ConversationalAgent.ts @@ -1,5 +1,5 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface' -import { initializeAgentExecutorWithOptions, AgentExecutor } from 'langchain/agents' +import { initializeAgentExecutorWithOptions, AgentExecutor, InitializeAgentExecutorOptions } from 'langchain/agents' import { Tool } from 'langchain/tools' import { BaseChatModel } from 'langchain/chat_models/base' import { BaseChatMemory } from 'langchain/memory' @@ -39,6 +39,22 @@ class ConversationalAgent_Agents implements INode { label: 'Memory', name: 'memory', type: 'BaseChatMemory' + }, + { + label: 'System Message', + name: 'systemMessage', + type: 'string', + rows: 4, + optional: true, + additionalParams: true + }, + { + label: 'Human Message', + name: 'humanMessage', + type: 'string', + rows: 4, + optional: true, + additionalParams: true } ] } @@ -47,11 +63,25 @@ class ConversationalAgent_Agents implements INode { const model = nodeData.inputs?.model as BaseChatModel const tools = nodeData.inputs?.tools as Tool[] const memory = nodeData.inputs?.memory as BaseChatMemory + const humanMessage = nodeData.inputs?.humanMessage as string + const systemMessage = nodeData.inputs?.systemMessage as string - const executor = await initializeAgentExecutorWithOptions(tools, model, { + const obj: InitializeAgentExecutorOptions = { agentType: 'chat-conversational-react-description', verbose: true - }) + } + + const agentArgs: any = {} + if (humanMessage) { + agentArgs.humanMessage = humanMessage + } + if (systemMessage) { + agentArgs.systemMessage = systemMessage + } + + if (Object.keys(agentArgs).length) obj.agentArgs = agentArgs + + const executor = await initializeAgentExecutorWithOptions(tools, model, obj) executor.memory = memory return executor } diff --git a/packages/components/src/Interface.ts b/packages/components/src/Interface.ts index 44c87d746..181cc206e 100644 --- a/packages/components/src/Interface.ts +++ b/packages/components/src/Interface.ts @@ -49,6 +49,7 @@ export interface INodeParams { acceptVariable?: boolean placeholder?: string fileType?: string + additionalParams?: boolean } export interface INodeExecutionData { diff --git a/packages/ui/src/ui-component/dialog/AdditionalParamsDialog.js b/packages/ui/src/ui-component/dialog/AdditionalParamsDialog.js new file mode 100644 index 000000000..66a1eaf64 --- /dev/null +++ b/packages/ui/src/ui-component/dialog/AdditionalParamsDialog.js @@ -0,0 +1,64 @@ +import { createPortal } from 'react-dom' +import { useState, useEffect } from 'react' +import PropTypes from 'prop-types' +import { Dialog, DialogContent } from '@mui/material' +import PerfectScrollbar from 'react-perfect-scrollbar' +import NodeInputHandler from 'views/canvas/NodeInputHandler' + +const AdditionalParamsDialog = ({ show, dialogProps, onCancel }) => { + const portalElement = document.getElementById('portal') + + const [inputParams, setInputParams] = useState([]) + const [data, setData] = useState({}) + + useEffect(() => { + if (dialogProps.inputParams) setInputParams(dialogProps.inputParams) + if (dialogProps.data) setData(dialogProps.data) + + return () => { + setInputParams([]) + setData({}) + } + }, [dialogProps]) + + const component = show ? ( + + + + {inputParams.map((inputParam, index) => ( + + ))} + + + + ) : null + + return createPortal(component, portalElement) +} + +AdditionalParamsDialog.propTypes = { + show: PropTypes.bool, + dialogProps: PropTypes.object, + onCancel: PropTypes.func +} + +export default AdditionalParamsDialog diff --git a/packages/ui/src/views/canvas/CanvasNode.js b/packages/ui/src/views/canvas/CanvasNode.js index 75e2f7dae..c59b288d3 100644 --- a/packages/ui/src/views/canvas/CanvasNode.js +++ b/packages/ui/src/views/canvas/CanvasNode.js @@ -1,14 +1,15 @@ import PropTypes from 'prop-types' -import { useContext } from 'react' +import { useContext, useState } from 'react' // material-ui import { styled, useTheme } from '@mui/material/styles' -import { IconButton, Box, Typography, Divider } from '@mui/material' +import { IconButton, Box, Typography, Divider, Button } from '@mui/material' // project imports import MainCard from 'ui-component/cards/MainCard' import NodeInputHandler from './NodeInputHandler' import NodeOutputHandler from './NodeOutputHandler' +import AdditionalParamsDialog from 'ui-component/dialog/AdditionalParamsDialog' // const import { baseURL } from 'store/constant' @@ -35,6 +36,20 @@ const CanvasNode = ({ data }) => { const theme = useTheme() const { deleteNode, duplicateNode } = useContext(flowContext) + const [showDialog, setShowDialog] = useState(false) + const [dialogProps, setDialogProps] = useState({}) + + const onDialogClicked = () => { + const dialogProps = { + data, + inputParams: data.inputParams.filter((param) => param.additionalParams), + confirmButtonName: 'Save', + cancelButtonName: 'Cancel' + } + setDialogProps(dialogProps) + setShowDialog(true) + } + return ( <> { {data.inputParams.map((inputParam, index) => ( ))} - + {data.inputParams.find((param) => param.additionalParams) && ( + + + Additional Parameters + + + )} { ))} + setShowDialog(false)} + > > ) } diff --git a/packages/ui/src/views/canvas/NodeInputHandler.js b/packages/ui/src/views/canvas/NodeInputHandler.js index 686448ad2..dfa9943e9 100644 --- a/packages/ui/src/views/canvas/NodeInputHandler.js +++ b/packages/ui/src/views/canvas/NodeInputHandler.js @@ -24,7 +24,7 @@ const CustomWidthTooltip = styled(({ className, ...props }) => { +const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false, isAdditionalParams = false }) => { const theme = useTheme() const ref = useRef(null) const { reactFlowInstance } = useContext(flowContext) @@ -96,7 +96,7 @@ const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false }) = > )} - {inputParam && ( + {((inputParam && !inputParam.additionalParams) || isAdditionalParams) && ( <> {inputParam.acceptVariable && ( @@ -186,7 +186,8 @@ NodeInputHandler.propTypes = { inputAnchor: PropTypes.object, inputParam: PropTypes.object, data: PropTypes.object, - disabled: PropTypes.bool + disabled: PropTypes.bool, + isAdditionalParams: PropTypes.bool } export default NodeInputHandler diff --git a/packages/ui/src/views/marketplaces/MarketplaceCanvasNode.js b/packages/ui/src/views/marketplaces/MarketplaceCanvasNode.js index d27a7df4a..8ec5ada30 100644 --- a/packages/ui/src/views/marketplaces/MarketplaceCanvasNode.js +++ b/packages/ui/src/views/marketplaces/MarketplaceCanvasNode.js @@ -1,13 +1,15 @@ import PropTypes from 'prop-types' +import { useState } from 'react' // material-ui import { styled, useTheme } from '@mui/material/styles' -import { Box, Typography, Divider } from '@mui/material' +import { Box, Typography, Divider, Button } from '@mui/material' // project imports import MainCard from 'ui-component/cards/MainCard' import NodeInputHandler from 'views/canvas/NodeInputHandler' import NodeOutputHandler from 'views/canvas/NodeOutputHandler' +import AdditionalParamsDialog from 'ui-component/dialog/AdditionalParamsDialog' // const import { baseURL } from 'store/constant' @@ -31,6 +33,21 @@ const CardWrapper = styled(MainCard)(({ theme }) => ({ const MarketplaceCanvasNode = ({ data }) => { const theme = useTheme() + const [showDialog, setShowDialog] = useState(false) + const [dialogProps, setDialogProps] = useState({}) + + const onDialogClicked = () => { + const dialogProps = { + data, + inputParams: data.inputParams.filter((param) => param.additionalParams), + disabled: true, + confirmButtonName: 'Save', + cancelButtonName: 'Cancel' + } + setDialogProps(dialogProps) + setShowDialog(true) + } + return ( <> { {data.inputParams.map((inputParam, index) => ( ))} - + {data.inputParams.find((param) => param.additionalParams) && ( + + + Additional Parameters + + + )} { ))} + setShowDialog(false)} + > > ) }