### What problem does this PR solve? feat: run flow #918 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.8.0
| return { data, loading, deleteFlow: mutateAsync }; | return { data, loading, deleteFlow: mutateAsync }; | ||||
| }; | }; | ||||
| export const useRunFlow = () => { | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: ['runFlow'], | |||||
| mutationFn: async (params: { id: string; dsl: DSL }) => { | |||||
| const { data } = await flowService.runCanvas(params); | |||||
| if (data.retcode === 0) { | |||||
| message.success(i18n.t(`message.modified`)); | |||||
| } | |||||
| return data?.data ?? {}; | |||||
| }, | |||||
| }); | |||||
| return { data, loading, runFlow: mutateAsync }; | |||||
| }; |
| import { ModelVariableType } from '@/constants/knowledge'; | |||||
| export enum Operator { | export enum Operator { | ||||
| Begin = 'Begin', | Begin = 'Begin', | ||||
| Retrieval = 'Retrieval', | Retrieval = 'Retrieval', | ||||
| }; | }; | ||||
| export const initialGenerateValues = { | export const initialGenerateValues = { | ||||
| parameters: ModelVariableType.Precise, | |||||
| temperatureEnabled: false, | |||||
| // parameters: ModelVariableType.Precise, | |||||
| // temperatureEnabled: true, | |||||
| temperature: 0.1, | temperature: 0.1, | ||||
| top_p: 0.3, | top_p: 0.3, | ||||
| frequency_penalty: 0.7, | frequency_penalty: 0.7, | ||||
| The above is the content you need to summarize.`, | The above is the content you need to summarize.`, | ||||
| cite: true, | cite: true, | ||||
| }; | }; | ||||
| export const initialFormValuesMap = { | |||||
| [Operator.Begin]: initialBeginValues, | |||||
| [Operator.Retrieval]: initialRetrievalValues, | |||||
| [Operator.Generate]: initialGenerateValues, | |||||
| [Operator.Answer]: {}, | |||||
| }; |
| import { Button, Flex } from 'antd'; | import { Button, Flex } from 'antd'; | ||||
| import { useSaveGraph } from '../hooks'; | |||||
| import { useRunGraph, useSaveGraph } from '../hooks'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const FlowHeader = () => { | const FlowHeader = () => { | ||||
| const { saveGraph } = useSaveGraph(); | const { saveGraph } = useSaveGraph(); | ||||
| const { runGraph } = useRunGraph(); | |||||
| return ( | return ( | ||||
| <Flex | <Flex | ||||
| gap={'large'} | gap={'large'} | ||||
| className={styles.flowHeader} | className={styles.flowHeader} | ||||
| > | > | ||||
| <Button> | |||||
| <Button onClick={runGraph}> | |||||
| <b>Debug</b> | <b>Debug</b> | ||||
| </Button> | </Button> | ||||
| <Button type="primary" onClick={saveGraph}> | <Button type="primary" onClick={saveGraph}> |
| import { | import { | ||||
| useFetchFlow, | useFetchFlow, | ||||
| useFetchFlowTemplates, | useFetchFlowTemplates, | ||||
| useRunFlow, | |||||
| useSetFlow, | useSetFlow, | ||||
| } from '@/hooks/flow-hooks'; | } from '@/hooks/flow-hooks'; | ||||
| import { useFetchLlmList } from '@/hooks/llmHooks'; | import { useFetchLlmList } from '@/hooks/llmHooks'; | ||||
| x: 0, | x: 0, | ||||
| y: 0, | y: 0, | ||||
| }, | }, | ||||
| data: { label: `${type}` }, | |||||
| data: { | |||||
| label: `${type}`, | |||||
| }, | |||||
| sourcePosition: Position.Right, | sourcePosition: Position.Right, | ||||
| targetPosition: Position.Left, | targetPosition: Position.Left, | ||||
| }; | }; | ||||
| const { nodes, edges } = useStore((state) => state); | const { nodes, edges } = useStore((state) => state); | ||||
| const saveGraph = useCallback(() => { | const saveGraph = useCallback(() => { | ||||
| const dslComponents = buildDslComponentsByGraph(nodes, edges); | const dslComponents = buildDslComponentsByGraph(nodes, edges); | ||||
| console.info('components:', dslComponents); | |||||
| setFlow({ | setFlow({ | ||||
| id, | id, | ||||
| title: data.title, | title: data.title, | ||||
| export const useFlowIsFetching = () => { | export const useFlowIsFetching = () => { | ||||
| return useIsFetching({ queryKey: ['flowDetail'] }) > 0; | return useIsFetching({ queryKey: ['flowDetail'] }) > 0; | ||||
| }; | }; | ||||
| export const useRunGraph = () => { | |||||
| const { data } = useFetchFlow(); | |||||
| const { runFlow } = useRunFlow(); | |||||
| const { id } = useParams(); | |||||
| const { nodes, edges } = useStore((state) => state); | |||||
| const runGraph = useCallback(() => { | |||||
| const dslComponents = buildDslComponentsByGraph(nodes, edges); | |||||
| runFlow({ | |||||
| id: id!!, | |||||
| dsl: { ...data.dsl, components: dslComponents }, | |||||
| }); | |||||
| }, [nodes, edges, runFlow, id, data]); | |||||
| return { runGraph }; | |||||
| }; |
| }, | }, | ||||
| }, | }, | ||||
| history: [], | history: [], | ||||
| path: ['begin'], | |||||
| path: [], | |||||
| answer: [], | answer: [], | ||||
| }; | }; |
| import { DSLComponents } from '@/interfaces/database/flow'; | import { DSLComponents } from '@/interfaces/database/flow'; | ||||
| import { removeUselessFieldsFromValues } from '@/utils/form'; | import { removeUselessFieldsFromValues } from '@/utils/form'; | ||||
| import dagre from 'dagre'; | import dagre from 'dagre'; | ||||
| import { curry, isEmpty } from 'lodash'; | |||||
| import pipe from 'lodash/fp/pipe'; | |||||
| import { Edge, MarkerType, Node, Position } from 'reactflow'; | import { Edge, MarkerType, Node, Position } from 'reactflow'; | ||||
| import { v4 as uuidv4 } from 'uuid'; | import { v4 as uuidv4 } from 'uuid'; | ||||
| import { Operator, initialFormValuesMap } from './constant'; | |||||
| import { NodeData } from './interface'; | import { NodeData } from './interface'; | ||||
| const buildEdges = ( | const buildEdges = ( | ||||
| .map((y) => y[isBuildDownstream ? 'target' : 'source']); | .map((y) => y[isBuildDownstream ? 'target' : 'source']); | ||||
| }; | }; | ||||
| const removeUselessDataInTheOperator = ( | |||||
| operatorName: string, | |||||
| params: Record<string, unknown>, | |||||
| ) => { | |||||
| if (operatorName === 'Generate') { | |||||
| return removeUselessFieldsFromValues(params, ''); | |||||
| const removeUselessDataInTheOperator = curry( | |||||
| (operatorName: string, params: Record<string, unknown>) => { | |||||
| if (operatorName === Operator.Generate) { | |||||
| return removeUselessFieldsFromValues(params, ''); | |||||
| } | |||||
| return params; | |||||
| }, | |||||
| ); | |||||
| // initialize data for operators without parameters | |||||
| const initializeOperatorParams = curry((operatorName: string, values: any) => { | |||||
| if (isEmpty(values)) { | |||||
| return initialFormValuesMap[operatorName as Operator]; | |||||
| } | } | ||||
| return params; | |||||
| }; | |||||
| return values; | |||||
| }); | |||||
| const buildOperatorParams = (operatorName: string) => | |||||
| pipe( | |||||
| removeUselessDataInTheOperator(operatorName), | |||||
| initializeOperatorParams(operatorName), // Final processing, for guarantee | |||||
| ); | |||||
| // construct a dsl based on the node information of the graph | // construct a dsl based on the node information of the graph | ||||
| export const buildDslComponentsByGraph = ( | export const buildDslComponentsByGraph = ( | ||||
| components[id] = { | components[id] = { | ||||
| obj: { | obj: { | ||||
| component_name: operatorName, | component_name: operatorName, | ||||
| // params: | |||||
| // removeUselessDataInTheOperator( | |||||
| // operatorName, | |||||
| // x.data.form as Record<string, unknown>, | |||||
| // ) ?? {}, | |||||
| params: | params: | ||||
| removeUselessDataInTheOperator( | |||||
| operatorName, | |||||
| buildOperatorParams(operatorName)( | |||||
| x.data.form as Record<string, unknown>, | x.data.form as Record<string, unknown>, | ||||
| ) ?? {}, | ) ?? {}, | ||||
| }, | }, |
| listCanvas, | listCanvas, | ||||
| resetCanvas, | resetCanvas, | ||||
| removeCanvas, | removeCanvas, | ||||
| runCanvas, | |||||
| listTemplates, | listTemplates, | ||||
| } = api; | } = api; | ||||
| url: removeCanvas, | url: removeCanvas, | ||||
| method: 'post', | method: 'post', | ||||
| }, | }, | ||||
| runCanvas: { | |||||
| url: runCanvas, | |||||
| method: 'post', | |||||
| }, | |||||
| listTemplates: { | listTemplates: { | ||||
| url: listTemplates, | url: listTemplates, | ||||
| method: 'get', | method: 'get', |
| removeCanvas: `${api_host}/canvas/rm`, | removeCanvas: `${api_host}/canvas/rm`, | ||||
| setCanvas: `${api_host}/canvas/set`, | setCanvas: `${api_host}/canvas/set`, | ||||
| resetCanvas: `${api_host}/canvas/reset`, | resetCanvas: `${api_host}/canvas/reset`, | ||||
| runCanvas: `${api_host}/canvas/run`, | |||||
| }; | }; |
| // chat model setting and generate operator | // chat model setting and generate operator | ||||
| export const excludeUnEnabledVariables = ( | export const excludeUnEnabledVariables = ( | ||||
| values: any, | |||||
| values: any = {}, | |||||
| prefix = 'llm_setting.', | prefix = 'llm_setting.', | ||||
| ) => { | ) => { | ||||
| const unEnabledFields: Array<keyof typeof variableEnabledFieldMap> = | const unEnabledFields: Array<keyof typeof variableEnabledFieldMap> = |