From 07d7965e3ba536c6d6f12c5252df2a9314d68ab5 Mon Sep 17 00:00:00 2001 From: JzoNg Date: Tue, 24 Dec 2024 16:25:50 +0800 Subject: [PATCH] support custom output schema in tool node --- web/app/components/tools/types.ts | 1 + .../block-selector/tool/action-item.tsx | 1 + .../workflow/block-selector/types.ts | 1 + .../nodes/_base/components/variable/utils.ts | 24 +++++++++++++++++- .../components/workflow/nodes/tool/panel.tsx | 9 +++++++ .../components/workflow/nodes/tool/types.ts | 1 + .../workflow/nodes/tool/use-config.ts | 25 ++++++++++++++++--- 7 files changed, 58 insertions(+), 4 deletions(-) diff --git a/web/app/components/tools/types.ts b/web/app/components/tools/types.ts index 27f187d1f7..19432f4217 100644 --- a/web/app/components/tools/types.ts +++ b/web/app/components/tools/types.ts @@ -76,6 +76,7 @@ export type Tool = { description: any parameters: ToolParameter[] labels: string[] + output_schema: Record } export type ToolCredential = { diff --git a/web/app/components/workflow/block-selector/tool/action-item.tsx b/web/app/components/workflow/block-selector/tool/action-item.tsx index 7a7abe9e03..bc8db404a0 100644 --- a/web/app/components/workflow/block-selector/tool/action-item.tsx +++ b/web/app/components/workflow/block-selector/tool/action-item.tsx @@ -58,6 +58,7 @@ const ToolItem: FC = ({ tool_label: payload.label[language], title: payload.label[language], is_team_authorization: provider.is_team_authorization, + output_schema: payload.output_schema, params, }) }} diff --git a/web/app/components/workflow/block-selector/types.ts b/web/app/components/workflow/block-selector/types.ts index ffe6cc627c..d0fc7782f9 100644 --- a/web/app/components/workflow/block-selector/types.ts +++ b/web/app/components/workflow/block-selector/types.ts @@ -27,4 +27,5 @@ export type ToolDefaultValue = { title: string is_team_authorization: boolean params: Record + output_schema: Record } diff --git a/web/app/components/workflow/nodes/_base/components/variable/utils.ts b/web/app/components/workflow/nodes/_base/components/variable/utils.ts index 7ad8bcd834..277a0fa287 100644 --- a/web/app/components/workflow/nodes/_base/components/variable/utils.ts +++ b/web/app/components/workflow/nodes/_base/components/variable/utils.ts @@ -235,7 +235,29 @@ const formatItem = ( } case BlockEnum.Tool: { - res.vars = TOOL_OUTPUT_STRUCT + const { + output_schema, + } = data as ToolNodeType + if (!output_schema) { + res.vars = TOOL_OUTPUT_STRUCT + } + else { + const outputSchema: any[] = [] + Object.keys(output_schema.properties).forEach((outputKey) => { + const output = output_schema.properties[outputKey] + outputSchema.push({ + variable: outputKey, + type: output.type === 'array' + ? `Array[${output.items?.type.slice(0, 1).toLocaleUpperCase()}${output.items?.type.slice(1)}]` + : `${output.type.slice(0, 1).toLocaleUpperCase()}${output.type.slice(1)}`, + description: output.description, + }) + }) + res.vars = [ + ...TOOL_OUTPUT_STRUCT, + ...outputSchema, + ] + } break } diff --git a/web/app/components/workflow/nodes/tool/panel.tsx b/web/app/components/workflow/nodes/tool/panel.tsx index d0d4c3a839..d93e5b8b5c 100644 --- a/web/app/components/workflow/nodes/tool/panel.tsx +++ b/web/app/components/workflow/nodes/tool/panel.tsx @@ -49,6 +49,7 @@ const Panel: FC> = ({ handleRun, handleStop, runResult, + outputSchema, } = useConfig(id, data) const toolIcon = useToolIcon(data) const { @@ -143,6 +144,14 @@ const Panel: FC> = ({ type='Array[Object]' description={t(`${i18nPrefix}.outputVars.json`)} /> + {outputSchema.map(outputItem => ( + + ))} diff --git a/web/app/components/workflow/nodes/tool/types.ts b/web/app/components/workflow/nodes/tool/types.ts index 60b6157f6d..4fbd945710 100644 --- a/web/app/components/workflow/nodes/tool/types.ts +++ b/web/app/components/workflow/nodes/tool/types.ts @@ -20,4 +20,5 @@ export type ToolNodeType = CommonNodeType & { tool_label: string tool_parameters: ToolVarInputs tool_configurations: Record + output_schema: Record } diff --git a/web/app/components/workflow/nodes/tool/use-config.ts b/web/app/components/workflow/nodes/tool/use-config.ts index be40a7fd1a..acc20ec7ea 100644 --- a/web/app/components/workflow/nodes/tool/use-config.ts +++ b/web/app/components/workflow/nodes/tool/use-config.ts @@ -29,8 +29,9 @@ const useConfig = (id: string, payload: ToolNodeType) => { /* * tool_configurations: tool setting, not dynamic setting * tool_parameters: tool dynamic setting(by user) + * output_schema: tool dynamic output */ - const { provider_id, provider_type, tool_name, tool_configurations } = inputs + const { provider_id, provider_type, tool_name, tool_configurations, output_schema } = inputs const isBuiltIn = provider_type === CollectionType.builtIn const buildInTools = useStore(s => s.buildInTools) const customTools = useStore(s => s.customTools) @@ -91,7 +92,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { const value = newConfig[key] if (schema?.type === 'boolean') { if (typeof value === 'string') - newConfig[key] = parseInt(value, 10) + newConfig[key] = Number.parseInt(value, 10) if (typeof value === 'boolean') newConfig[key] = value ? 1 : 0 @@ -99,7 +100,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { if (schema?.type === 'number-input') { if (typeof value === 'string' && value !== '') - newConfig[key] = parseFloat(value) + newConfig[key] = Number.parseFloat(value) } }) draft.tool_configurations = newConfig @@ -254,6 +255,23 @@ const useConfig = (id: string, payload: ToolNodeType) => { doHandleRun(addMissedVarData) } + const outputSchema = useMemo(() => { + const res: any[] = [] + if (!output_schema) + return [] + Object.keys(output_schema.properties).forEach((outputKey) => { + const output = output_schema.properties[outputKey] + res.push({ + name: outputKey, + type: output.type === 'array' + ? `Array[${output.items?.type.slice(0, 1).toLocaleUpperCase()}${output.items?.type.slice(1)}]` + : `${output.type.slice(0, 1).toLocaleUpperCase()}${output.type.slice(1)}`, + description: output.description, + }) + }) + return res + }, [output_schema]) + return { readOnly, inputs, @@ -282,6 +300,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { handleRun, handleStop, runResult, + outputSchema, } }