mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-07-06 07:15:12 +08:00
feat: fetch flow (#1068)
### 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)
This commit is contained in:
parent
b6980d8a16
commit
72c6784ff8
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"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",
|
||||||
|
@ -3,14 +3,18 @@ import { Form, Slider } from 'antd';
|
|||||||
|
|
||||||
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 (
|
||||||
@ -23,9 +27,9 @@ const SimilaritySlider = ({ isTooltipShown = false }: IProps) => {
|
|||||||
>
|
>
|
||||||
<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')}
|
||||||
>
|
>
|
||||||
|
@ -2,3 +2,11 @@ export enum MessageType {
|
|||||||
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',
|
||||||
|
};
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
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({
|
||||||
@ -15,7 +19,7 @@ export const useFetchFlowTemplates = () => {
|
|||||||
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: [],
|
||||||
@ -29,6 +33,21 @@ export const useFetchFlowList = () => {
|
|||||||
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 {
|
||||||
@ -37,9 +56,12 @@ export const useSetFlow = () => {
|
|||||||
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;
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
|
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[];
|
history?: any[];
|
||||||
path: string[];
|
path?: string[];
|
||||||
answer: any[];
|
answer?: any[];
|
||||||
|
graph?: IGraph;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IOperator {
|
export interface IOperator {
|
||||||
@ -17,3 +20,28 @@ export interface IOperatorNode {
|
|||||||
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;
|
||||||
|
}
|
||||||
|
@ -8,11 +8,8 @@ import { IDialog } from '@/interfaces/database/chat';
|
|||||||
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';
|
||||||
@ -20,6 +17,7 @@ import PromptEngine from './prompt-engine';
|
|||||||
|
|
||||||
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 = {
|
||||||
@ -76,11 +74,10 @@ const ChatConfigurationModal = ({
|
|||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
const values = await form.validateFields();
|
const values = await form.validateFields();
|
||||||
const nextValues: any = omit(values, [
|
const nextValues: any = removeUselessFieldsFromValues(
|
||||||
...Object.keys(variableEnabledFieldMap),
|
values,
|
||||||
'parameters',
|
'llm_setting.',
|
||||||
...excludeUnEnabledVariables(values),
|
);
|
||||||
]);
|
|
||||||
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);
|
||||||
|
@ -7,8 +7,8 @@ import { useEffect } from 'react';
|
|||||||
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 = ({
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
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',
|
||||||
|
@ -1,19 +1,8 @@
|
|||||||
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 !== '';
|
||||||
};
|
};
|
||||||
|
@ -15,9 +15,8 @@ const onFinishFailed: FormProps<FieldType>['onFinishFailed'] = (errorInfo) => {
|
|||||||
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
|
||||||
|
@ -1,6 +1,32 @@
|
|||||||
|
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,
|
||||||
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
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';
|
||||||
@ -26,8 +27,16 @@ const FlowDrawer = ({
|
|||||||
}: 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}
|
||||||
@ -39,7 +48,10 @@ const FlowDrawer = ({
|
|||||||
width={470}
|
width={470}
|
||||||
>
|
>
|
||||||
{visible && (
|
{visible && (
|
||||||
<OperatorForm onValuesChange={handleValuesChange}></OperatorForm>
|
<OperatorForm
|
||||||
|
onValuesChange={handleValuesChange}
|
||||||
|
form={form}
|
||||||
|
></OperatorForm>
|
||||||
)}
|
)}
|
||||||
</Drawer>
|
</Drawer>
|
||||||
);
|
);
|
||||||
|
@ -1,24 +1,23 @@
|
|||||||
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],
|
||||||
);
|
);
|
||||||
@ -38,7 +37,7 @@ const GenerateForm = ({ onValuesChange }: IOperatorForm) => {
|
|||||||
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 (
|
||||||
|
@ -1,9 +1,22 @@
|
|||||||
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';
|
||||||
|
|
||||||
@ -18,7 +31,8 @@ const selector = (state: RFState) => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -121,11 +135,19 @@ export const useHandleKeyUp = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
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);
|
const dslComponents = buildDslComponentsByGraph(nodes, edges);
|
||||||
console.info('components:', x);
|
console.info('components:', dslComponents);
|
||||||
}, [nodes, edges]);
|
setFlow({
|
||||||
|
id,
|
||||||
|
title: data.title,
|
||||||
|
dsl: { ...data.dsl, graph: { nodes, edges }, components: dslComponents },
|
||||||
|
});
|
||||||
|
}, [nodes, edges, setFlow, id, data]);
|
||||||
|
|
||||||
return { saveGraph };
|
return { saveGraph };
|
||||||
};
|
};
|
||||||
@ -145,7 +167,34 @@ export const useHandleFormValuesChange = (id?: string) => {
|
|||||||
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;
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Edge, Node } from 'reactflow';
|
import { FormInstance } from 'antd';
|
||||||
|
|
||||||
export interface DSLComponentList {
|
export interface DSLComponentList {
|
||||||
id: string;
|
id: string;
|
||||||
@ -7,6 +7,7 @@ export interface DSLComponentList {
|
|||||||
|
|
||||||
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 {
|
||||||
@ -40,23 +41,3 @@ export type NodeData = {
|
|||||||
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;
|
|
||||||
}
|
|
||||||
|
@ -11,7 +11,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
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 {
|
||||||
|
@ -31,8 +31,8 @@ const FlowList = () => {
|
|||||||
<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) => {
|
list.map((item) => {
|
||||||
return <FlowCard item={item} key={item.name}></FlowCard>;
|
return <FlowCard item={item} key={item.id}></FlowCard>;
|
||||||
})
|
})
|
||||||
) : (
|
) : (
|
||||||
<Empty className={styles.knowledgeEmpty}></Empty>
|
<Empty className={styles.knowledgeEmpty}></Empty>
|
||||||
|
@ -18,9 +18,7 @@ const onFinishFailed: FormProps<FieldType>['onFinishFailed'] = (errorInfo) => {
|
|||||||
console.log('Failed:', errorInfo);
|
console.log('Failed:', errorInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
const RetrievalForm = ({ onValuesChange }: IOperatorForm) => {
|
const RetrievalForm = ({ onValuesChange, form }: IOperatorForm) => {
|
||||||
const [form] = Form.useForm();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
name="basic"
|
name="basic"
|
||||||
@ -32,7 +30,10 @@ const RetrievalForm = ({ onValuesChange }: IOperatorForm) => {
|
|||||||
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>
|
||||||
|
@ -17,9 +17,6 @@ import {
|
|||||||
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>[];
|
||||||
@ -41,8 +38,8 @@ export type RFState = {
|
|||||||
// 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[],
|
nodes: [] as Node[],
|
||||||
edges: initialEdges as Edge[],
|
edges: [] as Edge[],
|
||||||
selectedNodeIds: [],
|
selectedNodeIds: [],
|
||||||
selectedEdgeIds: [],
|
selectedEdgeIds: [],
|
||||||
onNodesChange: (changes: NodeChange[]) => {
|
onNodesChange: (changes: NodeChange[]) => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
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';
|
||||||
@ -108,6 +109,16 @@ const buildComponentDownstreamOrUpstream = (
|
|||||||
.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>[],
|
||||||
@ -117,10 +128,15 @@ export const buildDslComponentsByGraph = (
|
|||||||
|
|
||||||
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,
|
component_name: operatorName,
|
||||||
params: x.data.form as Record<string, unknown>,
|
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),
|
||||||
|
28
web/src/utils/form.ts
Normal file
28
web/src/utils/form.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
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;
|
||||||
|
};
|
@ -1,7 +1,10 @@
|
|||||||
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 }>,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user