Skip to content

Commit

Permalink
feat: add tool params node & tool params add array type (#2824)
Browse files Browse the repository at this point in the history
* add tool params node

* add tool params enum

* node response

* tool add array type params

* fix tool params

* fix

* fix

* fix
  • Loading branch information
newfish-cmyk authored Sep 28, 2024
1 parent f2749cb commit 1599d14
Show file tree
Hide file tree
Showing 26 changed files with 437 additions and 27 deletions.
1 change: 1 addition & 0 deletions packages/global/core/workflow/node/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export enum FlowNodeTypeEnum {
queryExtension = 'cfr',
tools = 'tools',
stopTool = 'stopTool',
toolParams = 'toolParams',
lafModule = 'lafModule',
ifElseNode = 'ifElseNode',
variableUpdate = 'variableUpdate',
Expand Down
3 changes: 3 additions & 0 deletions packages/global/core/workflow/runtime/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ export type DispatchNodeResponseType = {

// form input
formInputResult?: string;

// tool params
toolParamsResult?: Record<string, any>;
};

export type DispatchNodeResultType<T = {}> = {
Expand Down
3 changes: 2 additions & 1 deletion packages/global/core/workflow/runtime/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ export const getReferenceVariableValue = ({
nodes: RuntimeNodeItemType[];
variables: Record<string, any>;
}) => {
if (!isReferenceValue(value)) {
const nodeIds = nodes.map((node) => node.nodeId);
if (!isReferenceValue(value, nodeIds)) {
return value;
}
const sourceNodeId = value[0];
Expand Down
6 changes: 4 additions & 2 deletions packages/global/core/workflow/template/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,19 @@ import { LoopNode } from './system/loop/loop';
import { LoopStartNode } from './system/loop/loopStart';
import { LoopEndNode } from './system/loop/loopEnd';
import { FormInputNode } from './system/interactive/formInput';
import { ToolParamsNode } from './system/toolParams';

const systemNodes: FlowNodeTemplateType[] = [
AiChatModule,
TextEditorNode,
AssignedAnswerModule,
DatasetSearchModule,
ClassifyQuestionModule,
ContextExtractModule,
DatasetConcatModule,
ToolModule,
ToolParamsNode,
StopToolNode,
ClassifyQuestionModule,
ContextExtractModule,
ReadFilesNode,
HttpNode468,
AiQueryExtension,
Expand Down
20 changes: 20 additions & 0 deletions packages/global/core/workflow/template/system/toolParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/node';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';

export const ToolParamsNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.toolParams,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.toolParams,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: 'core/workflow/template/toolParams',
name: i18nT('workflow:tool_params_config'),
intro: i18nT('workflow:intro_tool_params_config'),
version: '4811',
isTool: true,
inputs: [],
outputs: []
};
1 change: 1 addition & 0 deletions packages/global/core/workflow/type/io.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export type FlowNodeInputItemType = InputComponentPropsType & {
description?: string; // field desc
required?: boolean;
toolDescription?: string; // If this field is not empty, it is entered as a tool
enum?: string;

// render components params
canEdit?: boolean; // dynamic inputs
Expand Down
4 changes: 2 additions & 2 deletions packages/global/core/workflow/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ export const formatEditorVariablePickerIcon = (
}));
};

export const isReferenceValue = (value: any): boolean => {
return Array.isArray(value) && value.length === 2 && typeof value[0] === 'string';
export const isReferenceValue = (value: any, nodeIds: string[]): boolean => {
return Array.isArray(value) && value.length === 2 && nodeIds.includes(value[0]);
};

export const getElseIFLabel = (i: number) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,16 @@ export const runToolWithFunctionCall = async (
type: string;
description: string;
required?: boolean;
enum?: string[];
}
> = {};
item.toolParams.forEach((item) => {
const isArray = item.valueType?.startsWith('array');
properties[item.key] = {
type: item.valueType || 'string',
description: item.toolDescription || ''
type: isArray ? 'array' : item.valueType || 'string',
...(isArray && { items: { type: item.valueType?.slice(5).toLowerCase() || 'string' } }),
description: item.toolDescription || '',
enum: item.enum?.split('\n').filter(Boolean) || []
};
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,16 @@ export const runToolWithPromptCall = async (
type: string;
description: string;
required?: boolean;
enum?: string[];
}
> = {};
item.toolParams.forEach((item) => {
const isArray = item.valueType?.startsWith('array');
properties[item.key] = {
type: 'string',
description: item.toolDescription || ''
type: isArray ? 'array' : item.valueType || 'string',
...(isArray && { items: { type: item.valueType?.slice(5).toLowerCase() || 'string' } }),
description: item.toolDescription || '',
enum: item.enum?.split('\n').filter(Boolean) || []
};
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,20 @@ export const runToolWithToolChoice = async (
{
type: string;
description: string;
enum?: string[];
required?: boolean;
items?: {
type: string;
};
}
> = {};
item.toolParams.forEach((item) => {
const isArray = item.valueType?.startsWith('array');
properties[item.key] = {
type: item.valueType || 'string',
description: item.toolDescription || ''
type: isArray ? 'array' : item.valueType || 'string',
...(isArray && { items: { type: item.valueType?.slice(5).toLowerCase() || 'string' } }),
description: item.toolDescription || '',
enum: item.enum?.split('\n').filter(Boolean) || []
};
});

Expand Down Expand Up @@ -138,7 +145,6 @@ export const runToolWithToolChoice = async (
toolModel
);

// console.log(JSON.stringify(requestBody, null, 2));
/* Run llm */
const ai = getAIApi({
timeout: 480000
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type';

export type Props = ModuleDispatchProps<{}>;
export type Response = DispatchNodeResultType<{}>;

export const dispatchToolParams = (props: Props): Response => {
const { params } = props;

return {
...params,
[DispatchNodeResponseKeyEnum.nodeResponse]: {
toolParamsResult: params
}
};
};
2 changes: 2 additions & 0 deletions packages/service/core/workflow/dispatch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import { dispatchLoop } from './loop/runLoop';
import { dispatchLoopEnd } from './loop/runLoopEnd';
import { dispatchLoopStart } from './loop/runLoopStart';
import { dispatchFormInput } from './interactive/formInput';
import { dispatchToolParams } from './agent/runTool/toolParams';

const callbackMap: Record<FlowNodeTypeEnum, Function> = {
[FlowNodeTypeEnum.workflowStart]: dispatchWorkflowStart,
Expand All @@ -87,6 +88,7 @@ const callbackMap: Record<FlowNodeTypeEnum, Function> = {
[FlowNodeTypeEnum.queryExtension]: dispatchQueryExtension,
[FlowNodeTypeEnum.tools]: dispatchRunTools,
[FlowNodeTypeEnum.stopTool]: dispatchStopToolCall,
[FlowNodeTypeEnum.toolParams]: dispatchToolParams,
[FlowNodeTypeEnum.lafModule]: dispatchLafRequest,
[FlowNodeTypeEnum.ifElseNode]: dispatchIfElse,
[FlowNodeTypeEnum.variableUpdate]: dispatchUpdateVariable,
Expand Down
18 changes: 10 additions & 8 deletions packages/web/components/common/Icon/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ export const iconPaths = {
'common/importLight': () => import('./icons/common/importLight.svg'),
'common/info': () => import('./icons/common/info.svg'),
'common/inviteLight': () => import('./icons/common/inviteLight.svg'),
'common/language/America': () => import('./icons/common/language/America.svg'),
'common/language/China': () => import('./icons/common/language/China.svg'),
'common/language/en': () => import('./icons/common/language/en.svg'),
'common/language/zh': () => import('./icons/common/language/zh.svg'),
'common/language/China': () => import('./icons/common/language/China.svg'),
'common/language/America': () => import('./icons/common/language/America.svg'),
'common/leftArrowLight': () => import('./icons/common/leftArrowLight.svg'),
'common/line': () => import('./icons/common/line.svg'),
'common/lineChange': () => import('./icons/common/lineChange.svg'),
Expand Down Expand Up @@ -212,8 +212,10 @@ export const iconPaths = {
'core/workflow/runSkip': () => import('./icons/core/workflow/runSkip.svg'),
'core/workflow/runSuccess': () => import('./icons/core/workflow/runSuccess.svg'),
'core/workflow/running': () => import('./icons/core/workflow/running.svg'),
'core/workflow/template/BI': () => import('./icons/core/workflow/template/BI.svg'),
'core/workflow/template/FileRead': () => import('./icons/core/workflow/template/FileRead.svg'),
'core/workflow/template/aiChat': () => import('./icons/core/workflow/template/aiChat.svg'),
'core/workflow/template/baseChart': () => import('./icons/core/workflow/template/baseChart.svg'),
'core/workflow/template/codeRun': () => import('./icons/core/workflow/template/codeRun.svg'),
'core/workflow/template/customFeedback': () =>
import('./icons/core/workflow/template/customFeedback.svg'),
Expand Down Expand Up @@ -247,15 +249,17 @@ export const iconPaths = {
'core/workflow/template/reply': () => import('./icons/core/workflow/template/reply.svg'),
'core/workflow/template/runApp': () => import('./icons/core/workflow/template/runApp.svg'),
'core/workflow/template/stopTool': () => import('./icons/core/workflow/template/stopTool.svg'),
'core/workflow/template/toolkitActive': () =>
import('./icons/core/workflow/template/toolkitActive.svg'),
'core/workflow/template/toolkitInactive': () =>
import('./icons/core/workflow/template/toolkitInactive.svg'),
'core/workflow/template/systemConfig': () =>
import('./icons/core/workflow/template/systemConfig.svg'),
'core/workflow/template/textConcat': () =>
import('./icons/core/workflow/template/textConcat.svg'),
'core/workflow/template/toolCall': () => import('./icons/core/workflow/template/toolCall.svg'),
'core/workflow/template/toolParams': () =>
import('./icons/core/workflow/template/toolParams.svg'),
'core/workflow/template/toolkitActive': () =>
import('./icons/core/workflow/template/toolkitActive.svg'),
'core/workflow/template/toolkitInactive': () =>
import('./icons/core/workflow/template/toolkitInactive.svg'),
'core/workflow/template/userSelect': () =>
import('./icons/core/workflow/template/userSelect.svg'),
'core/workflow/template/variable': () => import('./icons/core/workflow/template/variable.svg'),
Expand All @@ -267,8 +271,6 @@ export const iconPaths = {
'core/workflow/undo': () => import('./icons/core/workflow/undo.svg'),
'core/workflow/upload': () => import('./icons/core/workflow/upload.svg'),
'core/workflow/versionHistories': () => import('./icons/core/workflow/versionHistories.svg'),
'core/workflow/template/baseChart': () => import('./icons/core/workflow/template/baseChart.svg'),
'core/workflow/template/BI': () => import('./icons/core/workflow/template/BI.svg'),
date: () => import('./icons/date.svg'),
delete: () => import('./icons/delete.svg'),
edit: () => import('./icons/edit.svg'),
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion packages/web/i18n/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"UnKnow": "Unknown",
"Warning": "Warning",
"add_new": "Add New",
"add_new_param": "Add new param",
"back": "Back",
"chose_condition": "Choose Condition",
"chosen": "Chosen",
Expand Down Expand Up @@ -1110,7 +1111,6 @@
"tag_list": "Tag List",
"team_tag": "Team Tag",
"textarea_variable_picker_tip": "Enter \"/\" to select a variable",
"tool_field": "Tool Field Parameter Configuration",
"undefined_var": "Referenced an undefined variable, add it automatically?",
"unit.character": "Character",
"unit.minute": "Minute",
Expand Down
12 changes: 12 additions & 0 deletions packages/web/i18n/en/workflow.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"create_link_error": "Error creating link",
"custom_feedback": "Custom Feedback",
"custom_input": "Custom Input",
"custom_tool_input": "Custom tool input",
"dataset_quote_role": "Role",
"dataset_quote_role_system_option_desc": "Historical records should be consistent first (recommended)",
"dataset_quote_role_tip": "When set to System, the knowledge base reference content will be placed in the system message, which can ensure the continuity of the history record, but the constraint effect may not be good.\n\nWhen set to User, the knowledge base reference content will be placed in the user message, and the {{question}} variable location needs to be specified. \nIt will have a certain impact on the consistency of historical records, but usually the constraint effect is better.",
Expand Down Expand Up @@ -78,6 +79,7 @@
"intro_text_concatenation": "Can process and output fixed or incoming text. Non-string type data will be converted to string type.",
"intro_text_content_extraction": "Can extract specified data from text, such as SQL statements, search keywords, code, etc.",
"intro_tool_call_termination": "This module needs to be configured for tool calls. When this module is executed, the current tool call will be forcibly terminated, and AI will no longer answer questions based on the tool call results.",
"intro_tool_params_config": " This module works with tool calls. It creates required tool parameters. Tool calls automatically generate parameter content and pass it to corresponding function blocks.",
"is_empty": "Is Empty",
"is_equal_to": "Is Equal To",
"is_not_empty": "Is Not Empty",
Expand Down Expand Up @@ -156,7 +158,17 @@
"text_to_extract": "Text to Extract",
"these_variables_will_be_input_parameters_for_code_execution": "These variables will be input parameters for code execution",
"tool_call_termination": "Tool Call Termination",
"tool_field": " Tool Field Parameter Configuration",
"tool_input": "Tool Input",
"tool_params.enum_placeholder": "apple \npeach \nwatermelon",
"tool_params.enum_values": "Enum values",
"tool_params.enum_values_tip": "List the possible values for this field, one per line",
"tool_params.params_description": "Description",
"tool_params.params_description_placeholder": "Name/Age/SQL statement..",
"tool_params.params_name": "Name",
"tool_params.params_name_placeholder": "name/age/sql",
"tool_params.tool_params_result": "Tool params result",
"tool_params_config": "Tool params config",
"trigger_after_application_completion": "Will be triggered after the application is fully completed",
"update_link_error": "Error updating link",
"update_specified_node_output_or_global_variable": "Can update the output value of a specified node or update global variables",
Expand Down
4 changes: 2 additions & 2 deletions packages/web/i18n/zh/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"UnKnow": "未知",
"Warning": "提示",
"add_new": "新增",
"add_new_param": "新增参数",
"back": "返回",
"chose_condition": "选择条件",
"chosen": "已选",
Expand Down Expand Up @@ -732,8 +733,8 @@
"core.module.template.empty_plugin": "空白插件",
"core.module.template.empty_workflow": "空白工作流",
"core.module.template.http body placeholder": "与 Apifox 相同的语法",
"core.module.template.self_output": "插件输出",
"core.module.template.self_input": "插件输入",
"core.module.template.self_output": "插件输出",
"core.module.template.system_config": "系统配置",
"core.module.template.system_config_info": "可以配置应用的系统参数",
"core.module.template.work_start": "流程开始",
Expand Down Expand Up @@ -1109,7 +1110,6 @@
"tag_list": "标签列表",
"team_tag": "团队标签",
"textarea_variable_picker_tip": "输入\"/\"可选择变量",
"tool_field": "工具字段参数配置",
"undefined_var": "引用了未定义的变量,是否自动添加?",
"unit.character": "字符",
"unit.minute": "分钟",
Expand Down
12 changes: 12 additions & 0 deletions packages/web/i18n/zh/workflow.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"create_link_error": "创建链接异常",
"custom_feedback": "自定义反馈",
"custom_input": "自定义输入",
"custom_tool_input": "自定义工具参数",
"dataset_quote_role": "角色",
"dataset_quote_role_system_option_desc": "历史记录连贯优先(推荐)",
"dataset_quote_role_tip": "设置为 System 时,将会把知识库引用内容放置到 system 消息中,可以确保历史记录的连贯性,但约束效果可能不佳,需要多调试。\n设置为 User 时,将会把知识库引用内容放置到 user 消息中,并且需要指定 {{question}} 变量位置。会对历史记录连贯性有一定影响,但通常约束效果更优。",
Expand Down Expand Up @@ -78,6 +79,7 @@
"intro_text_concatenation": "可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。",
"intro_text_content_extraction": "可从文本中提取指定的数据,例如:sql语句、搜索关键词、代码等",
"intro_tool_call_termination": "该模块需配置工具调用使用。当该模块被执行时,本次工具调用将会强制结束,并且不再调用AI针对工具调用结果回答问题。",
"intro_tool_params_config": "该模块需要配合工具调用使用。可以创建所需的工具参数,工具调用将自动生成参数内容并传给对应的功能块。",
"is_empty": "为空",
"is_equal_to": "等于",
"is_not_empty": "不为空",
Expand Down Expand Up @@ -156,7 +158,17 @@
"text_to_extract": "需要提取的文本",
"these_variables_will_be_input_parameters_for_code_execution": "这些变量会作为代码的运行的输入参数",
"tool_call_termination": "工具调用终止",
"tool_field": "工具参数配置",
"tool_input": "工具参数",
"tool_params.enum_placeholder": "apple \npeach \nwatermelon",
"tool_params.enum_values": "枚举值(可选)",
"tool_params.enum_values_tip": "列举出该字段可能的值,每行一个",
"tool_params.params_description": "参数描述",
"tool_params.params_description_placeholder": "姓名/年龄/SQL 语句...",
"tool_params.params_name": "参数名",
"tool_params.params_name_placeholder": "name/age/sql",
"tool_params.tool_params_result": "参数配置结果",
"tool_params_config": "工具参数配置",
"trigger_after_application_completion": "将在应用完全结束后触发",
"update_link_error": "更新链接异常",
"update_specified_node_output_or_global_variable": "可以更新指定节点的输出值或更新全局变量",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,12 @@ export const WholeResponseContent = ({

{/* form input */}
<Row label={t('workflow:form_input_result')} value={activeModule?.formInputResult} />

{/* tool params */}
<Row
label={t('workflow:tool_params.tool_params_result')}
value={activeModule?.toolParamsResult}
/>
</Box>
) : null;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,12 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => {
if (item.flowNodeType === FlowNodeTypeEnum.lafModule && !feConfigs.lafEnv) {
return false;
}
// tool stop
if (!hasToolNode && item.flowNodeType === FlowNodeTypeEnum.stopTool) {
// tool stop or tool params
if (
!hasToolNode &&
(item.flowNodeType === FlowNodeTypeEnum.stopTool ||
item.flowNodeType === FlowNodeTypeEnum.toolParams)
) {
return false;
}
return true;
Expand Down
Loading

0 comments on commit 1599d14

Please sign in to comment.