diff --git a/client/src/components/ChatBox/index.tsx b/client/src/components/ChatBox/index.tsx index 3ed732858..c7936e5b3 100644 --- a/client/src/components/ChatBox/index.tsx +++ b/client/src/components/ChatBox/index.tsx @@ -38,7 +38,7 @@ import { fileDownload } from '@/utils/file'; import { htmlTemplate } from '@/constants/common'; import { useRouter } from 'next/router'; import { useGlobalStore } from '@/store/global'; -import { TaskResponseKeyEnum } from '@/constants/chat'; +import { TaskResponseKeyEnum, getDefaultChatVariables } from '@/constants/chat'; import MyIcon from '@/components/Icon'; import Avatar from '@/components/Avatar'; @@ -251,7 +251,7 @@ const ChatBox = ( * user confirm send prompt */ const sendPrompt = useCallback( - async (data: Record = {}, inputVal = '') => { + async (variables: Record = {}, inputVal = '') => { if (isChatting) { toast({ title: '正在聊天中...请等待结束', @@ -306,7 +306,10 @@ const ChatBox = ( messages, controller: abortSignal, generatingMessage, - variables: data + variables: { + ...getDefaultChatVariables(), + ...variables + } }); // set finish status diff --git a/client/src/constants/chat.ts b/client/src/constants/chat.ts index 9a64defee..b51b5f619 100644 --- a/client/src/constants/chat.ts +++ b/client/src/constants/chat.ts @@ -1,3 +1,5 @@ +import dayjs from 'dayjs'; + export enum sseResponseEventEnum { error = 'error', answer = 'answer', @@ -65,3 +67,7 @@ export enum OutLinkTypeEnum { export const HUMAN_ICON = `https://fastgpt.run/icon/human.png`; export const LOGO_ICON = `https://fastgpt.run/icon/logo.png`; + +export const getDefaultChatVariables = () => ({ + cTime: dayjs().format('YYYY/MM/DD HH:mm:ss') +}); diff --git a/client/src/constants/flow/ModuleTemplate.ts b/client/src/constants/flow/ModuleTemplate.ts index 0c4ff410e..f2a3c868d 100644 --- a/client/src/constants/flow/ModuleTemplate.ts +++ b/client/src/constants/flow/ModuleTemplate.ts @@ -30,7 +30,7 @@ export const VariableModule: FlowModuleTemplateType = { name: '全局变量', intro: '可以在对话开始前,要求用户填写一些内容作为本轮对话的变量。该模块位于开场引导之后。', description: - '全局变量可以通过 {{变量key}} 的形式注入到其他模块的文本中。目前支持:提示词、限定词。', + '全局变量可以通过 {{变量key}} 的形式注入到其他模块 string 类型的输入中,例如:提示词、限定词等', flowType: FlowModuleTypeEnum.variable, inputs: [ { @@ -389,6 +389,7 @@ export const ContextExtractModule: FlowModuleTemplateType = { valueType: FlowValueTypeEnum.string, label: '提取要求描述', description: '写一段提取要求,告诉 AI 需要提取哪些内容', + required: true, placeholder: '例如: \n1. 你是一个实验室预约助手。根据用户问题,提取出姓名、实验室号和预约时间', value: '' @@ -433,8 +434,8 @@ export const ContextExtractModule: FlowModuleTemplateType = { { key: ContextExtractEnum.fields, label: '完整提取结果', - description: '一个 JSON 对象,例如 {"name:":"YY","Time":"2023/7/2 18:00"}', - valueType: FlowValueTypeEnum.any, + description: '一个 JSON 字符串,例如:{"name:":"YY","Time":"2023/7/2 18:00"}', + valueType: FlowValueTypeEnum.string, type: FlowOutputItemTypeEnum.source, targets: [] }, diff --git a/client/src/pages/app/detail/components/AdEdit/components/Nodes/NodeExtract.tsx b/client/src/pages/app/detail/components/AdEdit/components/Nodes/NodeExtract.tsx index f4d71cef3..4eaf07273 100644 --- a/client/src/pages/app/detail/components/AdEdit/components/Nodes/NodeExtract.tsx +++ b/client/src/pages/app/detail/components/AdEdit/components/Nodes/NodeExtract.tsx @@ -16,7 +16,7 @@ import { ContextExtractEnum } from '@/constants/flow/flowField'; import { FlowOutputItemTypeEnum, FlowValueTypeEnum } from '@/constants/flow'; const NodeExtract = ({ - data: { inputs, outputs, moduleId, onChangeNode, ...props } + data: { inputs, outputs, moduleId, onChangeNode, onDelEdge, ...props } }: NodeProps) => { const { t } = useTranslation(); const [editExtractFiled, setEditExtractField] = useState(); @@ -105,6 +105,7 @@ const NodeExtract = ({ key: '', value: newOutputVal }); + onDelEdge({ moduleId, sourceHandle: item.key }); }} /> @@ -168,6 +169,10 @@ const NodeExtract = ({ value: newOutputs }); + if (editExtractFiled.key && editExtractFiled.key !== data.key) { + onDelEdge({ moduleId, sourceHandle: editExtractFiled.key }); + } + setEditExtractField(undefined); }} /> diff --git a/client/src/pages/app/detail/components/AdEdit/index.tsx b/client/src/pages/app/detail/components/AdEdit/index.tsx index 3a47c4afe..6761996bf 100644 --- a/client/src/pages/app/detail/components/AdEdit/index.tsx +++ b/client/src/pages/app/detail/components/AdEdit/index.tsx @@ -162,7 +162,6 @@ const AppEdit = ({ app, fullScreen, onFullScreen }: Props) => { }); return modules; }, [edges, nodes]); - const onChangeNode = useCallback( ({ moduleId, key, type = 'inputs', value, valueKey = 'value' }: FlowModuleItemChangeProps) => { setNodes((nodes) => @@ -205,6 +204,29 @@ const AppEdit = ({ app, fullScreen, onFullScreen }: Props) => { }, [setEdges, setNodes] ); + const onDelEdge = useCallback( + ({ + moduleId, + sourceHandle, + targetHandle + }: { + moduleId: string; + sourceHandle?: string; + targetHandle?: string; + }) => { + if (!sourceHandle && !targetHandle) return; + setEdges((state) => + state.filter((edge) => { + if (edge.source === moduleId && edge.sourceHandle === sourceHandle) return false; + if (edge.target === moduleId && edge.targetHandle === targetHandle) return false; + + return true; + }) + ); + }, + [setEdges] + ); + const onAddNode = useCallback( ({ template, position }: { template: FlowModuleTemplateType; position: XYPosition }) => { if (!reactFlowWrapper.current) return; @@ -221,12 +243,13 @@ const AppEdit = ({ app, fullScreen, onFullScreen }: Props) => { position: { x: mouseX, y: mouseY } }, onChangeNode, - onDelNode + onDelNode, + onDelEdge }) ) ); }, - [onChangeNode, onDelNode, setNodes, x, y, zoom] + [onDelEdge, onChangeNode, onDelNode, setNodes, x, y, zoom] ); const onDelConnect = useCallback( (id: string) => { @@ -309,14 +332,15 @@ const AppEdit = ({ app, fullScreen, onFullScreen }: Props) => { appModule2FlowNode({ item, onChangeNode, - onDelNode + onDelNode, + onDelEdge }) ) ); onFixView(); }, - [onDelConnect, setEdges, setNodes, onFixView, onChangeNode, onDelNode] + [onDelConnect, setEdges, setNodes, onFixView, onChangeNode, onDelNode, onDelEdge] ); useEffect(() => { diff --git a/client/src/service/moduleDispatch/agent/extract.ts b/client/src/service/moduleDispatch/agent/extract.ts index c364ce6d1..7a5ea90eb 100644 --- a/client/src/service/moduleDispatch/agent/extract.ts +++ b/client/src/service/moduleDispatch/agent/extract.ts @@ -19,7 +19,7 @@ export type Props = { export type Response = { [ContextExtractEnum.success]?: boolean; [ContextExtractEnum.failed]?: boolean; - [ContextExtractEnum.fields]: Record; + [ContextExtractEnum.fields]: string; [TaskResponseKeyEnum.responseData]: ChatHistoryItemResType; }; @@ -115,7 +115,7 @@ export async function dispatchContentExtract({ return { [ContextExtractEnum.success]: success ? true : undefined, [ContextExtractEnum.failed]: success ? undefined : true, - [ContextExtractEnum.fields]: arg, + [ContextExtractEnum.fields]: JSON.stringify(arg), ...arg, [TaskResponseKeyEnum.responseData]: { moduleName: ChatModuleEnum.Extract, diff --git a/client/src/types/flow.d.ts b/client/src/types/flow.d.ts index 6ed9df9d6..085888e16 100644 --- a/client/src/types/flow.d.ts +++ b/client/src/types/flow.d.ts @@ -59,4 +59,13 @@ export type FlowModuleItemType = FlowModuleTemplateType & { moduleId: string; onChangeNode: (e: FlowModuleItemChangeProps) => void; onDelNode: (id: string) => void; + onDelEdge: ({ + moduleId, + sourceHandle, + targetHandle + }: { + moduleId: string; + sourceHandle?: string | undefined; + targetHandle?: string | undefined; + }) => void; }; diff --git a/client/src/utils/adapt.ts b/client/src/utils/adapt.ts index bf0c54050..eb5460b51 100644 --- a/client/src/utils/adapt.ts +++ b/client/src/utils/adapt.ts @@ -63,11 +63,13 @@ export const textAdaptGptResponse = ({ export const appModule2FlowNode = ({ item, onChangeNode, - onDelNode + onDelNode, + onDelEdge }: { item: AppModuleItemType; onChangeNode: FlowModuleItemType['onChangeNode']; onDelNode: FlowModuleItemType['onDelNode']; + onDelEdge: FlowModuleItemType['onDelEdge']; }): Node => { // init some static data const template = @@ -96,7 +98,8 @@ export const appModule2FlowNode = ({ }; }), onChangeNode, - onDelNode + onDelNode, + onDelEdge }; return {