mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
Feat: Outputs data is directly synchronized to the canvas without going through the form. #10427 (#11406)
### What problem does this PR solve? Feat: Outputs data is directly synchronized to the canvas without going through the form. #10427 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -22,7 +22,8 @@ import { Switch } from '@/components/ui/switch';
|
|||||||
import { LlmModelType } from '@/constants/knowledge';
|
import { LlmModelType } from '@/constants/knowledge';
|
||||||
import { useFindLlmByUuid } from '@/hooks/use-llm-request';
|
import { useFindLlmByUuid } from '@/hooks/use-llm-request';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { memo, useCallback, useEffect, useMemo } from 'react';
|
import { get } from 'lodash';
|
||||||
|
import { memo, useEffect, useMemo } from 'react';
|
||||||
import { useForm, useWatch } from 'react-hook-form';
|
import { useForm, useWatch } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
@ -45,7 +46,10 @@ import { AgentTools, Agents } from './agent-tools';
|
|||||||
import { StructuredOutputDialog } from './structured-output-dialog';
|
import { StructuredOutputDialog } from './structured-output-dialog';
|
||||||
import { StructuredOutputPanel } from './structured-output-panel';
|
import { StructuredOutputPanel } from './structured-output-panel';
|
||||||
import { useBuildPromptExtraPromptOptions } from './use-build-prompt-options';
|
import { useBuildPromptExtraPromptOptions } from './use-build-prompt-options';
|
||||||
import { useShowStructuredOutputDialog } from './use-show-structured-output-dialog';
|
import {
|
||||||
|
useHandleShowStructuredOutput,
|
||||||
|
useShowStructuredOutputDialog,
|
||||||
|
} from './use-show-structured-output-dialog';
|
||||||
import { useValues } from './use-values';
|
import { useValues } from './use-values';
|
||||||
import { useWatchFormChange } from './use-watch-change';
|
import { useWatchFormChange } from './use-watch-change';
|
||||||
|
|
||||||
@ -121,22 +125,19 @@ function AgentForm({ node }: INextOperatorForm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
initialStructuredOutput,
|
|
||||||
showStructuredOutputDialog,
|
showStructuredOutputDialog,
|
||||||
structuredOutputDialogVisible,
|
structuredOutputDialogVisible,
|
||||||
hideStructuredOutputDialog,
|
hideStructuredOutputDialog,
|
||||||
handleStructuredOutputDialogOk,
|
handleStructuredOutputDialogOk,
|
||||||
} = useShowStructuredOutputDialog(node?.id);
|
} = useShowStructuredOutputDialog(node?.id);
|
||||||
|
|
||||||
const updateNodeForm = useGraphStore((state) => state.updateNodeForm);
|
const structuredOutput = get(
|
||||||
|
node,
|
||||||
|
`data.form.outputs.${AgentStructuredOutputField}`,
|
||||||
|
);
|
||||||
|
|
||||||
const handleShowStructuredOutput = useCallback(
|
const { handleShowStructuredOutput } = useHandleShowStructuredOutput(
|
||||||
(val: boolean) => {
|
node?.id,
|
||||||
if (node?.id && val) {
|
|
||||||
updateNodeForm(node?.id, {}, ['outputs', AgentStructuredOutputField]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[node?.id, updateNodeForm],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -327,7 +328,7 @@ function AgentForm({ node }: INextOperatorForm) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StructuredOutputPanel
|
<StructuredOutputPanel
|
||||||
value={initialStructuredOutput}
|
value={structuredOutput}
|
||||||
></StructuredOutputPanel>
|
></StructuredOutputPanel>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
@ -337,7 +338,7 @@ function AgentForm({ node }: INextOperatorForm) {
|
|||||||
<StructuredOutputDialog
|
<StructuredOutputDialog
|
||||||
hideModal={hideStructuredOutputDialog}
|
hideModal={hideStructuredOutputDialog}
|
||||||
onOk={handleStructuredOutputDialogOk}
|
onOk={handleStructuredOutputDialogOk}
|
||||||
initialValues={initialStructuredOutput}
|
initialValues={structuredOutput}
|
||||||
></StructuredOutputDialog>
|
></StructuredOutputDialog>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { JSONSchema } from '@/components/jsonjoy-builder';
|
import { JSONSchema } from '@/components/jsonjoy-builder';
|
||||||
|
import { AgentStructuredOutputField } from '@/constants/agent';
|
||||||
import { useSetModalState } from '@/hooks/common-hooks';
|
import { useSetModalState } from '@/hooks/common-hooks';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
import { initialAgentValues } from '../../constant';
|
||||||
import useGraphStore from '../../store';
|
import useGraphStore from '../../store';
|
||||||
|
|
||||||
export function useShowStructuredOutputDialog(nodeId?: string) {
|
export function useShowStructuredOutputDialog(nodeId?: string) {
|
||||||
@ -9,15 +11,13 @@ export function useShowStructuredOutputDialog(nodeId?: string) {
|
|||||||
showModal: showStructuredOutputDialog,
|
showModal: showStructuredOutputDialog,
|
||||||
hideModal: hideStructuredOutputDialog,
|
hideModal: hideStructuredOutputDialog,
|
||||||
} = useSetModalState();
|
} = useSetModalState();
|
||||||
const { updateNodeForm, getNode } = useGraphStore((state) => state);
|
const { updateNodeForm } = useGraphStore((state) => state);
|
||||||
|
|
||||||
const initialStructuredOutput = getNode(nodeId)?.data.form.outputs.structured;
|
|
||||||
|
|
||||||
const handleStructuredOutputDialogOk = useCallback(
|
const handleStructuredOutputDialogOk = useCallback(
|
||||||
(values: JSONSchema) => {
|
(values: JSONSchema) => {
|
||||||
// Sync data to canvas
|
// Sync data to canvas
|
||||||
if (nodeId) {
|
if (nodeId) {
|
||||||
updateNodeForm(nodeId, values, ['outputs', 'structured']);
|
updateNodeForm(nodeId, values, ['outputs', AgentStructuredOutputField]);
|
||||||
}
|
}
|
||||||
hideStructuredOutputDialog();
|
hideStructuredOutputDialog();
|
||||||
},
|
},
|
||||||
@ -25,10 +25,30 @@ export function useShowStructuredOutputDialog(nodeId?: string) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
initialStructuredOutput,
|
|
||||||
structuredOutputDialogVisible,
|
structuredOutputDialogVisible,
|
||||||
showStructuredOutputDialog,
|
showStructuredOutputDialog,
|
||||||
hideStructuredOutputDialog,
|
hideStructuredOutputDialog,
|
||||||
handleStructuredOutputDialogOk,
|
handleStructuredOutputDialogOk,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useHandleShowStructuredOutput(nodeId?: string) {
|
||||||
|
const updateNodeForm = useGraphStore((state) => state.updateNodeForm);
|
||||||
|
|
||||||
|
const handleShowStructuredOutput = useCallback(
|
||||||
|
(val: boolean) => {
|
||||||
|
if (nodeId) {
|
||||||
|
if (val) {
|
||||||
|
updateNodeForm(nodeId, {}, ['outputs', AgentStructuredOutputField]);
|
||||||
|
} else {
|
||||||
|
updateNodeForm(nodeId, initialAgentValues.outputs, ['outputs']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[nodeId, updateNodeForm],
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
handleShowStructuredOutput,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@ -6,8 +6,10 @@ import { initialAgentValues } from '../../constant';
|
|||||||
|
|
||||||
// You need to exclude the mcp and tools fields that are not in the form,
|
// You need to exclude the mcp and tools fields that are not in the form,
|
||||||
// otherwise the form data update will reset the tools or mcp data to an array
|
// otherwise the form data update will reset the tools or mcp data to an array
|
||||||
|
// Exclude data that is not in the form to avoid writing this data to the canvas when using useWatch.
|
||||||
|
// Outputs, tools, and MCP data are directly synchronized to the canvas without going through the form.
|
||||||
function omitToolsAndMcp(values: Record<string, any>) {
|
function omitToolsAndMcp(values: Record<string, any>) {
|
||||||
return omit(values, ['mcp', 'tools']);
|
return omit(values, ['mcp', 'tools', 'outputs']);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useValues(node?: RAGFlowNodeType) {
|
export function useValues(node?: RAGFlowNodeType) {
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { omit } from 'lodash';
|
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { UseFormReturn, useWatch } from 'react-hook-form';
|
import { UseFormReturn, useWatch } from 'react-hook-form';
|
||||||
import { AgentStructuredOutputField, PromptRole } from '../../constant';
|
import { PromptRole } from '../../constant';
|
||||||
import useGraphStore from '../../store';
|
import useGraphStore from '../../store';
|
||||||
|
|
||||||
export function useWatchFormChange(id?: string, form?: UseFormReturn<any>) {
|
export function useWatchFormChange(id?: string, form?: UseFormReturn<any>) {
|
||||||
@ -17,14 +16,6 @@ export function useWatchFormChange(id?: string, form?: UseFormReturn<any>) {
|
|||||||
prompts: [{ role: PromptRole.User, content: values.prompts }],
|
prompts: [{ role: PromptRole.User, content: values.prompts }],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!values.showStructuredOutput) {
|
|
||||||
nextValues = {
|
|
||||||
...nextValues,
|
|
||||||
outputs: omit(values.outputs, [AgentStructuredOutputField]),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
nextValues = omit(nextValues, 'outputs');
|
|
||||||
}
|
|
||||||
updateNodeForm(id, nextValues);
|
updateNodeForm(id, nextValues);
|
||||||
}
|
}
|
||||||
}, [form?.formState.isDirty, id, updateNodeForm, values]);
|
}, [form?.formState.isDirty, id, updateNodeForm, values]);
|
||||||
|
|||||||
Reference in New Issue
Block a user