### What problem does this PR solve? feat: fetch flow #918 feat: save graph ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.8.0
| { | { | ||||
| "private": true, | "private": true, | ||||
| "author": "zhaofengchao <13723060510@163.com>", | |||||
| "author": "bill", | |||||
| "scripts": { | "scripts": { | ||||
| "build": "umi build", | "build": "umi build", | ||||
| "dev": "cross-env UMI_DEV_SERVER_COMPRESS=none umi dev", | "dev": "cross-env UMI_DEV_SERVER_COMPRESS=none umi dev", |
| type FieldType = { | type FieldType = { | ||||
| similarity_threshold?: number; | similarity_threshold?: number; | ||||
| vector_similarity_weight?: number; | |||||
| // vector_similarity_weight?: number; | |||||
| }; | }; | ||||
| interface IProps { | interface IProps { | ||||
| isTooltipShown?: boolean; | isTooltipShown?: boolean; | ||||
| vectorSimilarityWeightName?: string; | |||||
| } | } | ||||
| const SimilaritySlider = ({ isTooltipShown = false }: IProps) => { | |||||
| const SimilaritySlider = ({ | |||||
| isTooltipShown = false, | |||||
| vectorSimilarityWeightName = 'vector_similarity_weight', | |||||
| }: IProps) => { | |||||
| const { t } = useTranslate('knowledgeDetails'); | const { t } = useTranslate('knowledgeDetails'); | ||||
| return ( | return ( | ||||
| > | > | ||||
| <Slider max={1} step={0.01} /> | <Slider max={1} step={0.01} /> | ||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item<FieldType> | |||||
| <Form.Item | |||||
| label={t('vectorSimilarityWeight')} | label={t('vectorSimilarityWeight')} | ||||
| name={'vector_similarity_weight'} | |||||
| name={vectorSimilarityWeightName} | |||||
| initialValue={1 - 0.3} | initialValue={1 - 0.3} | ||||
| tooltip={isTooltipShown && t('vectorSimilarityWeightTip')} | tooltip={isTooltipShown && t('vectorSimilarityWeightTip')} | ||||
| > | > |
| Assistant = 'assistant', | Assistant = 'assistant', | ||||
| User = 'user', | User = 'user', | ||||
| } | } | ||||
| export const variableEnabledFieldMap = { | |||||
| temperatureEnabled: 'temperature', | |||||
| topPEnabled: 'top_p', | |||||
| presencePenaltyEnabled: 'presence_penalty', | |||||
| frequencyPenaltyEnabled: 'frequency_penalty', | |||||
| maxTokensEnabled: 'max_tokens', | |||||
| }; |
| import { DSL, IFlow } from '@/interfaces/database/flow'; | |||||
| import i18n from '@/locales/config'; | |||||
| import flowService from '@/services/flow-service'; | import flowService from '@/services/flow-service'; | ||||
| import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; | import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; | ||||
| import { message } from 'antd'; | |||||
| import { useParams } from 'umi'; | |||||
| export const useFetchFlowTemplates = () => { | export const useFetchFlowTemplates = () => { | ||||
| const { data } = useQuery({ | const { data } = useQuery({ | ||||
| return data; | return data; | ||||
| }; | }; | ||||
| export const useFetchFlowList = () => { | |||||
| export const useFetchFlowList = (): { data: IFlow[]; loading: boolean } => { | |||||
| const { data, isFetching: loading } = useQuery({ | const { data, isFetching: loading } = useQuery({ | ||||
| queryKey: ['fetchFlowList'], | queryKey: ['fetchFlowList'], | ||||
| initialData: [], | initialData: [], | ||||
| return { data, loading }; | return { data, loading }; | ||||
| }; | }; | ||||
| export const useFetchFlow = (): { data: IFlow; loading: boolean } => { | |||||
| const { id } = useParams(); | |||||
| const { data, isFetching: loading } = useQuery({ | |||||
| queryKey: ['flowDetail'], | |||||
| initialData: {} as IFlow, | |||||
| queryFn: async () => { | |||||
| const { data } = await flowService.getCanvas({}, id); | |||||
| return data?.data ?? {}; | |||||
| }, | |||||
| }); | |||||
| return { data, loading }; | |||||
| }; | |||||
| export const useSetFlow = () => { | export const useSetFlow = () => { | ||||
| const queryClient = useQueryClient(); | const queryClient = useQueryClient(); | ||||
| const { | const { | ||||
| mutateAsync, | mutateAsync, | ||||
| } = useMutation({ | } = useMutation({ | ||||
| mutationKey: ['setFlow'], | mutationKey: ['setFlow'], | ||||
| mutationFn: async (params: any) => { | |||||
| mutationFn: async (params: { id?: string; title?: string; dsl?: DSL }) => { | |||||
| const { data } = await flowService.setCanvas(params); | const { data } = await flowService.setCanvas(params); | ||||
| if (data.retcode === 0) { | if (data.retcode === 0) { | ||||
| message.success( | |||||
| i18n.t(`message.${params?.id ? 'modified' : 'created'}`), | |||||
| ); | |||||
| queryClient.invalidateQueries({ queryKey: ['fetchFlowList'] }); | queryClient.invalidateQueries({ queryKey: ['fetchFlowList'] }); | ||||
| } | } | ||||
| return data?.retcode; | return data?.retcode; |
| import { Edge, Node } from 'reactflow'; | |||||
| export type DSLComponents = Record<string, IOperator>; | export type DSLComponents = Record<string, IOperator>; | ||||
| export interface DSL { | export interface DSL { | ||||
| components: DSLComponents; | components: DSLComponents; | ||||
| history: any[]; | |||||
| path: string[]; | |||||
| answer: any[]; | |||||
| history?: any[]; | |||||
| path?: string[]; | |||||
| answer?: any[]; | |||||
| graph?: IGraph; | |||||
| } | } | ||||
| export interface IOperator { | export interface IOperator { | ||||
| component_name: string; | component_name: string; | ||||
| params: Record<string, unknown>; | params: Record<string, unknown>; | ||||
| } | } | ||||
| export interface IGraph { | |||||
| nodes: Node[]; | |||||
| edges: Edge[]; | |||||
| } | |||||
| export interface IFlow { | |||||
| avatar: null; | |||||
| canvas_type: null; | |||||
| create_date: string; | |||||
| create_time: number; | |||||
| description: null; | |||||
| dsl: { | |||||
| answer: any[]; | |||||
| components: DSLComponents; | |||||
| graph: IGraph; | |||||
| history: any[]; | |||||
| path: string[]; | |||||
| }; | |||||
| id: string; | |||||
| title: string; | |||||
| update_date: string; | |||||
| update_time: number; | |||||
| user_id: string; | |||||
| } |
| import { Divider, Flex, Form, Modal, Segmented, UploadFile } from 'antd'; | import { Divider, Flex, Form, Modal, Segmented, UploadFile } from 'antd'; | ||||
| import { SegmentedValue } from 'antd/es/segmented'; | import { SegmentedValue } from 'antd/es/segmented'; | ||||
| import camelCase from 'lodash/camelCase'; | import camelCase from 'lodash/camelCase'; | ||||
| import omit from 'lodash/omit'; | |||||
| import { useEffect, useRef, useState } from 'react'; | import { useEffect, useRef, useState } from 'react'; | ||||
| import { variableEnabledFieldMap } from '../constants'; | |||||
| import { IPromptConfigParameters } from '../interface'; | import { IPromptConfigParameters } from '../interface'; | ||||
| import { excludeUnEnabledVariables } from '../utils'; | |||||
| import AssistantSetting from './assistant-setting'; | import AssistantSetting from './assistant-setting'; | ||||
| import { useFetchLlmModelOnVisible, useFetchModelId } from './hooks'; | import { useFetchLlmModelOnVisible, useFetchModelId } from './hooks'; | ||||
| import ModelSetting from './model-setting'; | import ModelSetting from './model-setting'; | ||||
| import { useTranslate } from '@/hooks/commonHooks'; | import { useTranslate } from '@/hooks/commonHooks'; | ||||
| import { getBase64FromUploadFileList } from '@/utils/fileUtil'; | import { getBase64FromUploadFileList } from '@/utils/fileUtil'; | ||||
| import { removeUselessFieldsFromValues } from '@/utils/form'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const layout = { | const layout = { | ||||
| const handleOk = async () => { | const handleOk = async () => { | ||||
| const values = await form.validateFields(); | const values = await form.validateFields(); | ||||
| const nextValues: any = omit(values, [ | |||||
| ...Object.keys(variableEnabledFieldMap), | |||||
| 'parameters', | |||||
| ...excludeUnEnabledVariables(values), | |||||
| ]); | |||||
| const nextValues: any = removeUselessFieldsFromValues( | |||||
| values, | |||||
| 'llm_setting.', | |||||
| ); | |||||
| const emptyResponse = nextValues.prompt_config?.empty_response ?? ''; | const emptyResponse = nextValues.prompt_config?.empty_response ?? ''; | ||||
| const icon = await getBase64FromUploadFileList(values.icon); | const icon = await getBase64FromUploadFileList(values.icon); |
| import { ISegmentedContentProps } from '../interface'; | import { ISegmentedContentProps } from '../interface'; | ||||
| import LlmSettingItems from '@/components/llm-setting-items'; | import LlmSettingItems from '@/components/llm-setting-items'; | ||||
| import { variableEnabledFieldMap } from '@/constants/chat'; | |||||
| import { Variable } from '@/interfaces/database/chat'; | import { Variable } from '@/interfaces/database/chat'; | ||||
| import { variableEnabledFieldMap } from '../constants'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const ModelSetting = ({ | const ModelSetting = ({ |
| export const variableEnabledFieldMap = { | |||||
| temperatureEnabled: 'temperature', | |||||
| topPEnabled: 'top_p', | |||||
| presencePenaltyEnabled: 'presence_penalty', | |||||
| frequencyPenaltyEnabled: 'frequency_penalty', | |||||
| maxTokensEnabled: 'max_tokens', | |||||
| }; | |||||
| export enum ChatSearchParams { | export enum ChatSearchParams { | ||||
| DialogId = 'dialogId', | DialogId = 'dialogId', | ||||
| ConversationId = 'conversationId', | ConversationId = 'conversationId', |
| import { MessageType } from '@/constants/chat'; | import { MessageType } from '@/constants/chat'; | ||||
| import { IConversation, IReference } from '@/interfaces/database/chat'; | import { IConversation, IReference } from '@/interfaces/database/chat'; | ||||
| import { EmptyConversationId, variableEnabledFieldMap } from './constants'; | |||||
| import { EmptyConversationId } from './constants'; | |||||
| import { IClientConversation, IMessage } from './interface'; | import { IClientConversation, IMessage } from './interface'; | ||||
| export const excludeUnEnabledVariables = (values: any) => { | |||||
| const unEnabledFields: Array<keyof typeof variableEnabledFieldMap> = | |||||
| Object.keys(variableEnabledFieldMap).filter((key) => !values[key]) as Array< | |||||
| keyof typeof variableEnabledFieldMap | |||||
| >; | |||||
| return unEnabledFields.map( | |||||
| (key) => `llm_setting.${variableEnabledFieldMap[key]}`, | |||||
| ); | |||||
| }; | |||||
| export const isConversationIdExist = (conversationId: string) => { | export const isConversationIdExist = (conversationId: string) => { | ||||
| return conversationId !== EmptyConversationId && conversationId !== ''; | return conversationId !== EmptyConversationId && conversationId !== ''; | ||||
| }; | }; |
| console.log('Failed:', errorInfo); | console.log('Failed:', errorInfo); | ||||
| }; | }; | ||||
| const BeginForm = ({ onValuesChange }: IOperatorForm) => { | |||||
| const BeginForm = ({ onValuesChange, form }: IOperatorForm) => { | |||||
| const { t } = useTranslate('chat'); | const { t } = useTranslate('chat'); | ||||
| const [form] = Form.useForm(); | |||||
| return ( | return ( | ||||
| <Form | <Form |
| import { ModelVariableType } from '@/constants/knowledge'; | |||||
| export enum Operator { | export enum Operator { | ||||
| Begin = 'Begin', | Begin = 'Begin', | ||||
| Retrieval = 'Retrieval', | Retrieval = 'Retrieval', | ||||
| Generate = 'Generate', | Generate = 'Generate', | ||||
| Answer = 'Answer', | Answer = 'Answer', | ||||
| } | } | ||||
| export const initialRetrievalValues = { | |||||
| similarity_threshold: 0.2, | |||||
| keywords_similarity_weight: 0.3, | |||||
| top_n: 8, | |||||
| }; | |||||
| export const initialBeginValues = { | |||||
| prologue: `Hi! I'm your assistant, what can I do for you?`, | |||||
| }; | |||||
| export const initialGenerateValues = { | |||||
| parameters: ModelVariableType.Precise, | |||||
| temperatureEnabled: false, | |||||
| temperature: 0.1, | |||||
| top_p: 0.3, | |||||
| frequency_penalty: 0.7, | |||||
| presence_penalty: 0.4, | |||||
| max_tokens: 512, | |||||
| prompt: `Please summarize the following paragraphs. Be careful with the numbers, do not make things up. Paragraphs as following: | |||||
| {cluster_content} | |||||
| The above is the content you need to summarize.`, | |||||
| cite: true, | |||||
| }; |
| import { IModalProps } from '@/interfaces/common'; | import { IModalProps } from '@/interfaces/common'; | ||||
| import { Drawer } from 'antd'; | |||||
| import { Drawer, Form } from 'antd'; | |||||
| import { useEffect } from 'react'; | |||||
| import { Node } from 'reactflow'; | import { Node } from 'reactflow'; | ||||
| import AnswerForm from '../answer-form'; | import AnswerForm from '../answer-form'; | ||||
| import BeginForm from '../begin-form'; | import BeginForm from '../begin-form'; | ||||
| }: IModalProps<any> & IProps) => { | }: IModalProps<any> & IProps) => { | ||||
| const operatorName: Operator = node?.data.label; | const operatorName: Operator = node?.data.label; | ||||
| const OperatorForm = FormMap[operatorName]; | const OperatorForm = FormMap[operatorName]; | ||||
| const [form] = Form.useForm(); | |||||
| const { handleValuesChange } = useHandleFormValuesChange(node?.id); | const { handleValuesChange } = useHandleFormValuesChange(node?.id); | ||||
| useEffect(() => { | |||||
| if (visible) { | |||||
| form.setFieldsValue(node?.data?.form); | |||||
| } | |||||
| }, [visible, form, node?.data?.form]); | |||||
| return ( | return ( | ||||
| <Drawer | <Drawer | ||||
| title={node?.data.label} | title={node?.data.label} | ||||
| width={470} | width={470} | ||||
| > | > | ||||
| {visible && ( | {visible && ( | ||||
| <OperatorForm onValuesChange={handleValuesChange}></OperatorForm> | |||||
| <OperatorForm | |||||
| onValuesChange={handleValuesChange} | |||||
| form={form} | |||||
| ></OperatorForm> | |||||
| )} | )} | ||||
| </Drawer> | </Drawer> | ||||
| ); | ); |
| import LlmSettingItems from '@/components/llm-setting-items'; | import LlmSettingItems from '@/components/llm-setting-items'; | ||||
| import { variableEnabledFieldMap } from '@/constants/chat'; | |||||
| import { | import { | ||||
| ModelVariableType, | ModelVariableType, | ||||
| settledModelVariableMap, | settledModelVariableMap, | ||||
| } from '@/constants/knowledge'; | } from '@/constants/knowledge'; | ||||
| import { useTranslate } from '@/hooks/commonHooks'; | import { useTranslate } from '@/hooks/commonHooks'; | ||||
| import { Variable } from '@/interfaces/database/chat'; | import { Variable } from '@/interfaces/database/chat'; | ||||
| import { variableEnabledFieldMap } from '@/pages/chat/constants'; | |||||
| import { Form, Input, Switch } from 'antd'; | import { Form, Input, Switch } from 'antd'; | ||||
| import { useCallback, useEffect } from 'react'; | import { useCallback, useEffect } from 'react'; | ||||
| import { IOperatorForm } from '../interface'; | import { IOperatorForm } from '../interface'; | ||||
| const GenerateForm = ({ onValuesChange }: IOperatorForm) => { | |||||
| const GenerateForm = ({ onValuesChange, form }: IOperatorForm) => { | |||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); | ||||
| const [form] = Form.useForm(); | |||||
| const initialLlmSetting = undefined; | const initialLlmSetting = undefined; | ||||
| const handleParametersChange = useCallback( | const handleParametersChange = useCallback( | ||||
| (value: ModelVariableType) => { | (value: ModelVariableType) => { | ||||
| const variable = settledModelVariableMap[value]; | const variable = settledModelVariableMap[value]; | ||||
| form.setFieldsValue(variable); | |||||
| form?.setFieldsValue(variable); | |||||
| }, | }, | ||||
| [form], | [form], | ||||
| ); | ); | ||||
| return pre; | return pre; | ||||
| }, {}); | }, {}); | ||||
| const otherValues = settledModelVariableMap[ModelVariableType.Precise]; | const otherValues = settledModelVariableMap[ModelVariableType.Precise]; | ||||
| form.setFieldsValue({ ...switchBoxValues, ...otherValues }); | |||||
| form?.setFieldsValue({ ...switchBoxValues, ...otherValues }); | |||||
| }, [form, initialLlmSetting]); | }, [form, initialLlmSetting]); | ||||
| return ( | return ( |
| import { useSetModalState } from '@/hooks/commonHooks'; | import { useSetModalState } from '@/hooks/commonHooks'; | ||||
| import { useFetchFlowTemplates } from '@/hooks/flow-hooks'; | |||||
| import { | |||||
| useFetchFlow, | |||||
| useFetchFlowTemplates, | |||||
| useSetFlow, | |||||
| } from '@/hooks/flow-hooks'; | |||||
| import { useFetchLlmList } from '@/hooks/llmHooks'; | import { useFetchLlmList } from '@/hooks/llmHooks'; | ||||
| import React, { KeyboardEventHandler, useCallback, useState } from 'react'; | |||||
| import { IGraph } from '@/interfaces/database/flow'; | |||||
| import { useIsFetching } from '@tanstack/react-query'; | |||||
| import React, { | |||||
| KeyboardEventHandler, | |||||
| useCallback, | |||||
| useEffect, | |||||
| useState, | |||||
| } from 'react'; | |||||
| import { Node, Position, ReactFlowInstance } from 'reactflow'; | import { Node, Position, ReactFlowInstance } from 'reactflow'; | ||||
| import { v4 as uuidv4 } from 'uuid'; | import { v4 as uuidv4 } from 'uuid'; | ||||
| // import { shallow } from 'zustand/shallow'; | |||||
| import { useParams } from 'umi'; | |||||
| import useStore, { RFState } from './store'; | import useStore, { RFState } from './store'; | ||||
| import { buildDslComponentsByGraph } from './utils'; | import { buildDslComponentsByGraph } from './utils'; | ||||
| }); | }); | ||||
| export const useSelectCanvasData = () => { | export const useSelectCanvasData = () => { | ||||
| // return useStore(useShallow(selector)); throw error | |||||
| // return useStore(useShallow(selector)); // throw error | |||||
| // return useStore(selector, shallow); | |||||
| return useStore(selector); | return useStore(selector); | ||||
| }; | }; | ||||
| }; | }; | ||||
| export const useSaveGraph = () => { | export const useSaveGraph = () => { | ||||
| const { data } = useFetchFlow(); | |||||
| const { setFlow } = useSetFlow(); | |||||
| const { id } = useParams(); | |||||
| const { nodes, edges } = useStore((state) => state); | const { nodes, edges } = useStore((state) => state); | ||||
| const saveGraph = useCallback(() => { | const saveGraph = useCallback(() => { | ||||
| const x = buildDslComponentsByGraph(nodes, edges); | |||||
| console.info('components:', x); | |||||
| }, [nodes, edges]); | |||||
| const dslComponents = buildDslComponentsByGraph(nodes, edges); | |||||
| console.info('components:', dslComponents); | |||||
| setFlow({ | |||||
| id, | |||||
| title: data.title, | |||||
| dsl: { ...data.dsl, graph: { nodes, edges }, components: dslComponents }, | |||||
| }); | |||||
| }, [nodes, edges, setFlow, id, data]); | |||||
| return { saveGraph }; | return { saveGraph }; | ||||
| }; | }; | ||||
| return { handleValuesChange }; | return { handleValuesChange }; | ||||
| }; | }; | ||||
| const useSetGraphInfo = () => { | |||||
| const { setEdges, setNodes } = useStore((state) => state); | |||||
| const setGraphInfo = useCallback( | |||||
| ({ nodes = [], edges = [] }: IGraph) => { | |||||
| if (nodes.length && edges.length) { | |||||
| setNodes(nodes); | |||||
| setEdges(edges); | |||||
| } | |||||
| }, | |||||
| [setEdges, setNodes], | |||||
| ); | |||||
| return setGraphInfo; | |||||
| }; | |||||
| export const useFetchDataOnMount = () => { | export const useFetchDataOnMount = () => { | ||||
| const { loading, data } = useFetchFlow(); | |||||
| const setGraphInfo = useSetGraphInfo(); | |||||
| useEffect(() => { | |||||
| setGraphInfo(data?.dsl?.graph ?? {}); | |||||
| }, [setGraphInfo, data?.dsl?.graph]); | |||||
| useFetchFlowTemplates(); | useFetchFlowTemplates(); | ||||
| useFetchLlmList(); | useFetchLlmList(); | ||||
| return { loading, flowDetail: data }; | |||||
| }; | |||||
| export const useFlowIsFetching = () => { | |||||
| return useIsFetching({ queryKey: ['flowDetail'] }) > 0; | |||||
| }; | }; |
| import { Edge, Node } from 'reactflow'; | |||||
| import { FormInstance } from 'antd'; | |||||
| export interface DSLComponentList { | export interface DSLComponentList { | ||||
| id: string; | id: string; | ||||
| export interface IOperatorForm { | export interface IOperatorForm { | ||||
| onValuesChange?(changedValues: any, values: any): void; | onValuesChange?(changedValues: any, values: any): void; | ||||
| form?: FormInstance; | |||||
| } | } | ||||
| export interface IBeginForm { | export interface IBeginForm { | ||||
| color: string; | color: string; | ||||
| form: IBeginForm | IRetrievalForm | IGenerateForm; | form: IBeginForm | IRetrievalForm | IGenerateForm; | ||||
| }; | }; | ||||
| export interface IFlow { | |||||
| avatar: null; | |||||
| canvas_type: null; | |||||
| create_date: string; | |||||
| create_time: number; | |||||
| description: null; | |||||
| dsl: { | |||||
| answer: any[]; | |||||
| components: DSLComponentList; | |||||
| graph: { nodes: Node[]; edges: Edge[] }; | |||||
| history: any[]; | |||||
| path: string[]; | |||||
| }; | |||||
| id: string; | |||||
| title: string; | |||||
| update_date: string; | |||||
| update_time: number; | |||||
| user_id: string; | |||||
| } |
| import { useNavigate } from 'umi'; | import { useNavigate } from 'umi'; | ||||
| import { useDeleteFlow } from '@/hooks/flow-hooks'; | import { useDeleteFlow } from '@/hooks/flow-hooks'; | ||||
| import { IFlow } from '../../interface'; | |||||
| import { IFlow } from '@/interfaces/database/flow'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| interface IProps { | interface IProps { |
| <Spin spinning={loading}> | <Spin spinning={loading}> | ||||
| <Flex gap={'large'} wrap="wrap" className={styles.flowCardContainer}> | <Flex gap={'large'} wrap="wrap" className={styles.flowCardContainer}> | ||||
| {list.length > 0 ? ( | {list.length > 0 ? ( | ||||
| list.map((item: any) => { | |||||
| return <FlowCard item={item} key={item.name}></FlowCard>; | |||||
| list.map((item) => { | |||||
| return <FlowCard item={item} key={item.id}></FlowCard>; | |||||
| }) | }) | ||||
| ) : ( | ) : ( | ||||
| <Empty className={styles.knowledgeEmpty}></Empty> | <Empty className={styles.knowledgeEmpty}></Empty> |
| console.log('Failed:', errorInfo); | console.log('Failed:', errorInfo); | ||||
| }; | }; | ||||
| const RetrievalForm = ({ onValuesChange }: IOperatorForm) => { | |||||
| const [form] = Form.useForm(); | |||||
| const RetrievalForm = ({ onValuesChange, form }: IOperatorForm) => { | |||||
| return ( | return ( | ||||
| <Form | <Form | ||||
| name="basic" | name="basic" | ||||
| onValuesChange={onValuesChange} | onValuesChange={onValuesChange} | ||||
| form={form} | form={form} | ||||
| > | > | ||||
| <SimilaritySlider isTooltipShown></SimilaritySlider> | |||||
| <SimilaritySlider | |||||
| isTooltipShown | |||||
| vectorSimilarityWeightName="keywords_similarity_weight" | |||||
| ></SimilaritySlider> | |||||
| <TopNItem></TopNItem> | <TopNItem></TopNItem> | ||||
| <Rerank></Rerank> | <Rerank></Rerank> | ||||
| <KnowledgeBaseItem></KnowledgeBaseItem> | <KnowledgeBaseItem></KnowledgeBaseItem> |
| import { create } from 'zustand'; | import { create } from 'zustand'; | ||||
| import { devtools } from 'zustand/middleware'; | import { devtools } from 'zustand/middleware'; | ||||
| import { NodeData } from './interface'; | import { NodeData } from './interface'; | ||||
| import { dsl } from './mock'; | |||||
| const { nodes: initialNodes, edges: initialEdges } = dsl.graph; | |||||
| export type RFState = { | export type RFState = { | ||||
| nodes: Node<NodeData>[]; | nodes: Node<NodeData>[]; | ||||
| // this is our useStore hook that we can use in our components to get parts of the store and call actions | // this is our useStore hook that we can use in our components to get parts of the store and call actions | ||||
| const useStore = create<RFState>()( | const useStore = create<RFState>()( | ||||
| devtools((set, get) => ({ | devtools((set, get) => ({ | ||||
| nodes: initialNodes as Node[], | |||||
| edges: initialEdges as Edge[], | |||||
| nodes: [] as Node[], | |||||
| edges: [] as Edge[], | |||||
| selectedNodeIds: [], | selectedNodeIds: [], | ||||
| selectedEdgeIds: [], | selectedEdgeIds: [], | ||||
| onNodesChange: (changes: NodeChange[]) => { | onNodesChange: (changes: NodeChange[]) => { |
| import { DSLComponents } from '@/interfaces/database/flow'; | import { DSLComponents } from '@/interfaces/database/flow'; | ||||
| import { removeUselessFieldsFromValues } from '@/utils/form'; | |||||
| import dagre from 'dagre'; | import dagre from 'dagre'; | ||||
| 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'; | ||||
| .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, ''); | |||||
| } | |||||
| return params; | |||||
| }; | |||||
| // 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 = ( | ||||
| nodes: Node<NodeData>[], | nodes: Node<NodeData>[], | ||||
| nodes.forEach((x) => { | nodes.forEach((x) => { | ||||
| const id = x.id; | const id = x.id; | ||||
| const operatorName = x.data.label; | |||||
| components[id] = { | components[id] = { | ||||
| obj: { | obj: { | ||||
| component_name: x.data.label, | |||||
| params: x.data.form as Record<string, unknown>, | |||||
| component_name: operatorName, | |||||
| params: | |||||
| removeUselessDataInTheOperator( | |||||
| operatorName, | |||||
| x.data.form as Record<string, unknown>, | |||||
| ) ?? {}, | |||||
| }, | }, | ||||
| downstream: buildComponentDownstreamOrUpstream(edges, id, true), | downstream: buildComponentDownstreamOrUpstream(edges, id, true), | ||||
| upstream: buildComponentDownstreamOrUpstream(edges, id, false), | upstream: buildComponentDownstreamOrUpstream(edges, id, false), |
| import { variableEnabledFieldMap } from '@/constants/chat'; | |||||
| import omit from 'lodash/omit'; | |||||
| // chat model setting and generate operator | |||||
| export const excludeUnEnabledVariables = ( | |||||
| values: any, | |||||
| prefix = 'llm_setting.', | |||||
| ) => { | |||||
| const unEnabledFields: Array<keyof typeof variableEnabledFieldMap> = | |||||
| Object.keys(variableEnabledFieldMap).filter((key) => !values[key]) as Array< | |||||
| keyof typeof variableEnabledFieldMap | |||||
| >; | |||||
| return unEnabledFields.map( | |||||
| (key) => `${prefix}${variableEnabledFieldMap[key]}`, | |||||
| ); | |||||
| }; | |||||
| // chat model setting and generate operator | |||||
| export const removeUselessFieldsFromValues = (values: any, prefix?: string) => { | |||||
| const nextValues: any = omit(values, [ | |||||
| ...Object.keys(variableEnabledFieldMap), | |||||
| 'parameters', | |||||
| ...excludeUnEnabledVariables(values, prefix), | |||||
| ]); | |||||
| return nextValues; | |||||
| }; |
| import omit from 'lodash/omit'; | import omit from 'lodash/omit'; | ||||
| import { RequestMethod } from 'umi-request'; | import { RequestMethod } from 'umi-request'; | ||||
| type Service<T extends string> = Record<T, (params?: any) => any>; | |||||
| type Service<T extends string> = Record< | |||||
| T, | |||||
| (params?: any, urlAppendix?: string) => any | |||||
| >; | |||||
| const registerServer = <T extends string>( | const registerServer = <T extends string>( | ||||
| opt: Record<T, { url: string; method: string }>, | opt: Record<T, { url: string; method: string }>, |