feat: add form input node (#2773)

* add node

* dispatch

* extract InputTypeConfig component

* question tip

* fix build

* fix

* fix
This commit is contained in:
heheer
2024-09-26 13:48:03 +08:00
committed by GitHub
parent edebfdf5ef
commit 1cf76ee7df
34 changed files with 1326 additions and 419 deletions

View File

@@ -121,7 +121,7 @@ export const updateInteractiveChat = async ({
appId,
teamId,
tmbId,
userSelectedVal,
userInteractiveVal,
aiResponse,
newVariables,
newTitle
@@ -130,7 +130,7 @@ export const updateInteractiveChat = async ({
appId: string;
teamId: string;
tmbId: string;
userSelectedVal: string;
userInteractiveVal: string;
aiResponse: AIChatItemType & { dataId?: string };
newVariables?: Record<string, any>;
newTitle: string;
@@ -153,13 +153,38 @@ export const updateInteractiveChat = async ({
return;
}
interactiveValue.interactive = {
...interactiveValue.interactive,
params: {
...interactiveValue.interactive.params,
userSelectedVal
const parsedUserInteractiveVal = (() => {
try {
return JSON.parse(userInteractiveVal);
} catch (err) {
return userInteractiveVal;
}
};
})();
interactiveValue.interactive =
interactiveValue.interactive.type === 'userSelect'
? {
...interactiveValue.interactive,
params: {
...interactiveValue.interactive.params,
userSelectedVal: userInteractiveVal
}
}
: {
...interactiveValue.interactive,
params: {
...interactiveValue.interactive.params,
inputForm: interactiveValue.interactive.params.inputForm.map((item) => {
const itemValue = parsedUserInteractiveVal[item.label];
return itemValue !== undefined
? {
...item,
value: itemValue
}
: item;
}),
submitted: true
}
};
if (aiResponse.customFeedbacks) {
chatItem.customFeedbacks = chatItem.customFeedbacks

View File

@@ -64,11 +64,12 @@ import { dispatchUserSelect } from './interactive/userSelect';
import {
InteractiveNodeResponseItemType,
UserSelectInteractive
} from '@fastgpt/global/core/workflow/template/system/userSelect/type';
} from '@fastgpt/global/core/workflow/template/system/interactive/type';
import { dispatchRunAppNode } from './plugin/runApp';
import { dispatchLoop } from './loop/runLoop';
import { dispatchLoopEnd } from './loop/runLoopEnd';
import { dispatchLoopStart } from './loop/runLoopStart';
import { dispatchFormInput } from './interactive/formInput';
const callbackMap: Record<FlowNodeTypeEnum, Function> = {
[FlowNodeTypeEnum.workflowStart]: dispatchWorkflowStart,
@@ -97,6 +98,7 @@ const callbackMap: Record<FlowNodeTypeEnum, Function> = {
[FlowNodeTypeEnum.loop]: dispatchLoop,
[FlowNodeTypeEnum.loopStart]: dispatchLoopStart,
[FlowNodeTypeEnum.loopEnd]: dispatchLoopEnd,
[FlowNodeTypeEnum.formInput]: dispatchFormInput,
// none
[FlowNodeTypeEnum.systemConfig]: dispatchSystemConfig,
@@ -584,7 +586,10 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
// reset entry
runtimeNodes.forEach((item) => {
// Interactive node is not the entry node, return interactive result
if (item.flowNodeType !== FlowNodeTypeEnum.userSelect) {
if (
item.flowNodeType !== FlowNodeTypeEnum.userSelect &&
item.flowNodeType !== FlowNodeTypeEnum.formInput
) {
item.isEntry = false;
}
});

View File

@@ -0,0 +1,63 @@
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import {
DispatchNodeResultType,
ModuleDispatchProps
} from '@fastgpt/global/core/workflow/runtime/type';
import {
UserInputFormItemType,
UserInputInteractive
} from '@fastgpt/global/core/workflow/template/system/interactive/type';
type Props = ModuleDispatchProps<{
[NodeInputKeyEnum.description]: string;
[NodeInputKeyEnum.userInputForms]: UserInputFormItemType[];
}>;
type FormInputResponse = DispatchNodeResultType<{
[DispatchNodeResponseKeyEnum.interactive]?: UserInputInteractive;
[NodeOutputKeyEnum.formInputResult]?: Record<string, any>;
}>;
export const dispatchFormInput = async (props: Props): Promise<FormInputResponse> => {
const {
histories,
node,
params: { description, userInputForms },
query
} = props;
const { isEntry } = node;
// Interactive node is not the entry node, return interactive result
if (!isEntry) {
return {
[DispatchNodeResponseKeyEnum.interactive]: {
type: 'userInput',
params: {
description,
inputForm: userInputForms
}
}
};
}
node.isEntry = false;
const { text } = chatValue2RuntimePrompt(query);
const userInputVal = (() => {
try {
return JSON.parse(text);
} catch (error) {
return text;
}
})();
return {
[DispatchNodeResponseKeyEnum.rewriteHistories]: histories.slice(0, -2), // Removes the current session record as the history of subsequent nodes
...userInputVal,
[NodeOutputKeyEnum.formInputResult]: userInputVal,
[DispatchNodeResponseKeyEnum.nodeResponse]: {
formInputResult: userInputVal
}
};
};

View File

@@ -8,7 +8,7 @@ import { getHandleId } from '@fastgpt/global/core/workflow/utils';
import type {
UserSelectInteractive,
UserSelectOptionItemType
} from '@fastgpt/global/core/workflow/template/system/userSelect/type';
} from '@fastgpt/global/core/workflow/template/system/interactive/type';
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
type Props = ModuleDispatchProps<{