feat: add description text to operators and extract the useFetchModelId to logicHooks.ts and drag the operator to the canvas and initialize the form data #918 (#1379)

### What problem does this PR solve?

feat: add description text to operators #918 
feat: drag the operator to the canvas and initialize the form data #918
feat: extract the useFetchModelId to logicHooks.ts
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu 2024-07-04 19:18:02 +08:00 committed by GitHub
parent 306108fe0e
commit 25a8c076bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 171 additions and 102 deletions

View File

@ -4,10 +4,10 @@
display: inline-block;
}
.messageItemSectionLeft {
width: 70%;
width: 80%;
}
.messageItemSectionRight {
width: 40%;
width: 80%;
}
.messageItemContent {
display: inline-flex;

View File

@ -22,8 +22,13 @@ import { useTranslation } from 'react-i18next';
import { useDispatch } from 'umi';
import { useSetModalState, useTranslate } from './commonHooks';
import { useSetDocumentParser } from './documentHooks';
import { useFetchLlmList } from './llmHooks';
import { useOneNamespaceEffectsLoading } from './storeHooks';
import { useSaveSetting } from './userSettingHook';
import {
useFetchTenantInfo,
useSaveSetting,
useSelectTenantInfo,
} from './userSettingHook';
export const useChangeDocumentParser = (documentId: string) => {
const setDocumentParser = useSetDocumentParser();
@ -269,3 +274,26 @@ export const useSelectItem = (defaultId?: string) => {
return { selectedId, handleItemClick };
};
export const useFetchModelId = (visible: boolean) => {
const fetchTenantInfo = useFetchTenantInfo(false);
const tenantInfo = useSelectTenantInfo();
useEffect(() => {
if (visible) {
fetchTenantInfo();
}
}, [visible, fetchTenantInfo]);
return tenantInfo?.llm_id ?? '';
};
export const useFetchLlmModelOnVisible = (visible: boolean) => {
const fetchLlmList = useFetchLlmList();
useEffect(() => {
if (visible) {
fetchLlmList();
}
}, [fetchLlmList, visible]);
};

View File

@ -565,6 +565,17 @@ The above is the content you need to summarize.`,
componentId: 'component id',
add: 'Add',
operation: 'operation',
beginDescription: 'This is where the flow begin',
answerDescription: `This component is used as an interface between bot and human. It receives input of user and display the result of the computation of the bot.`,
retrievalDescription: `This component is for the process of retrieving relevent information from knowledge base. So, knowledgebases should be selected. If there's nothing retrieved, the 'Empty response' will be returned.`,
generateDescription: `This component is used to call LLM to generate text. Be careful about the prompt setting.`,
categorizeDescription: `This component is used to categorize text. Please specify the name, description and examples of the category. Every single category leads to different downstream components.`,
relevantDescription: `This component is used to judge if the retrieved information is relevent to user's question. 'Yes' represents that they're relevant. 'No' represents they're irrelevant.`,
rewriteQuestionDescription: `This component is used to refine user's quesion. Typically, when a user's original question can't retrieve relevant information from knowledge base, this component help you change the question into a proper one which might be more consistant with the expressions in knowledge base. Only 'Retrieval' can be its downstreams.`,
messageDescription:
'This component is used to send user static information.',
keywordDescription:
'This component is used to send user static information.',
},
footer: {
profile: 'All rights reserved @ React',

View File

@ -1,29 +0,0 @@
import { useFetchLlmList } from '@/hooks/llmHooks';
import {
useFetchTenantInfo,
useSelectTenantInfo,
} from '@/hooks/userSettingHook';
import { useEffect } from 'react';
export const useFetchModelId = (visible: boolean) => {
const fetchTenantInfo = useFetchTenantInfo(false);
const tenantInfo = useSelectTenantInfo();
useEffect(() => {
if (visible) {
fetchTenantInfo();
}
}, [visible, fetchTenantInfo]);
return tenantInfo?.llm_id ?? '';
};
export const useFetchLlmModelOnVisible = (visible: boolean) => {
const fetchLlmList = useFetchLlmList();
useEffect(() => {
if (visible) {
fetchLlmList();
}
}, [fetchLlmList, visible]);
};

View File

@ -11,11 +11,11 @@ import camelCase from 'lodash/camelCase';
import { useEffect, useRef, useState } from 'react';
import { IPromptConfigParameters } from '../interface';
import AssistantSetting from './assistant-setting';
import { useFetchLlmModelOnVisible, useFetchModelId } from './hooks';
import ModelSetting from './model-setting';
import PromptEngine from './prompt-engine';
import { useTranslate } from '@/hooks/commonHooks';
import { useFetchLlmModelOnVisible, useFetchModelId } from '@/hooks/logicHooks';
import { getBase64FromUploadFileList } from '@/utils/fileUtil';
import { removeUselessFieldsFromValues } from '@/utils/form';
import styles from './index.less';

View File

@ -1,16 +1,19 @@
import { useFetchFlow } from '@/hooks/flow-hooks';
import { IModalProps } from '@/interfaces/common';
import { Drawer } from 'antd';
import FlowChatBox from './box';
const ChatDrawer = ({ visible, hideModal }: IModalProps<any>) => {
const { data } = useFetchFlow();
return (
<Drawer
title="Debug"
title={data.title}
placement="right"
onClose={hideModal}
open={visible}
getContainer={false}
width={window.innerWidth > 1278 ? '30%' : 470}
width={window.innerWidth > 1278 ? '40%' : 470}
mask={false}
// zIndex={10000}
>

View File

@ -1,3 +1,4 @@
import { variableEnabledFieldMap } from '@/constants/chat';
import {
BranchesOutlined,
DatabaseOutlined,
@ -33,7 +34,7 @@ export const operatorIconMap = {
export const operatorMap = {
[Operator.Retrieval]: {
description: 'Retrieval description drjlftglrthjftl',
description: 'This is where the flow begin',
backgroundColor: '#cad6e0',
color: '#385974',
},
@ -47,7 +48,8 @@ export const operatorMap = {
color: '#996464',
},
[Operator.Answer]: {
description: 'Answer description',
description:
'This component is used as an interface between bot and human. It receives input of user and display the result of the computation of the bot.',
backgroundColor: '#f4816d',
color: 'white',
},
@ -126,7 +128,15 @@ export const initialBeginValues = {
prologue: `Hi! I'm your assistant, what can I do for you?`,
};
export const variableCheckBoxFieldMap = Object.keys(
variableEnabledFieldMap,
).reduce<Record<string, boolean>>((pre, cur) => {
pre[cur] = true;
return pre;
}, {});
const initialLlmBaseValues = {
...variableCheckBoxFieldMap,
temperature: 0.1,
top_p: 0.3,
frequency_penalty: 0.7,
@ -196,7 +206,14 @@ export const RestrictedUpstreamMap = {
[Operator.Answer]: [],
[Operator.Retrieval]: [],
[Operator.Generate]: [],
[Operator.Message]: [],
[Operator.Message]: [
Operator.Begin,
Operator.Message,
Operator.Generate,
Operator.Retrieval,
Operator.RewriteQuestion,
Operator.Categorize,
],
[Operator.Relevant]: [],
[Operator.RewriteQuestion]: [],
};

View File

@ -1,6 +1,7 @@
import { Card, Flex, Layout, Space, Typography } from 'antd';
import { useTranslate } from '@/hooks/commonHooks';
import { Card, Flex, Layout, Space, Tooltip } from 'antd';
import classNames from 'classnames';
import lowerFirst from 'lodash/lowerFirst';
import { componentMenuList } from '../constant';
import { useHandleDrag } from '../hooks';
import OperatorIcon from '../operator-icon';
@ -8,8 +9,6 @@ import styles from './index.less';
const { Sider } = Layout;
const { Text } = Typography;
interface IProps {
setCollapsed: (width: boolean) => void;
collapsed: boolean;
@ -17,6 +16,7 @@ interface IProps {
const FlowSide = ({ setCollapsed, collapsed }: IProps) => {
const { handleDragStart } = useHandleDrag();
const { t } = useTranslate('flow');
return (
<Sider
@ -40,13 +40,9 @@ const FlowSide = ({ setCollapsed, collapsed }: IProps) => {
<Space size={15}>
<OperatorIcon name={x.name}></OperatorIcon>
<section>
<Tooltip title={t(`${lowerFirst(x.name)}Description`)}>
<b>{x.name}</b>
<Text
ellipsis={{ tooltip: x.description }}
style={{ width: 130 }}
>
{x.description}
</Text>
</Tooltip>
</section>
</Space>
</Flex>

View File

@ -17,13 +17,25 @@ import {
ModelVariableType,
settledModelVariableMap,
} from '@/constants/knowledge';
import { useFetchModelId } from '@/hooks/logicHooks';
import { Variable } from '@/interfaces/database/chat';
import { useDebounceEffect } from 'ahooks';
import { FormInstance, message } from 'antd';
import { humanId } from 'human-id';
import trim from 'lodash/trim';
import { useParams } from 'umi';
import { NodeMap, Operator, RestrictedUpstreamMap } from './constant';
import {
NodeMap,
Operator,
RestrictedUpstreamMap,
initialBeginValues,
initialCategorizeValues,
initialGenerateValues,
initialMessageValues,
initialRelevantValues,
initialRetrievalValues,
initialRewriteQuestionValues,
} from './constant';
import useGraphStore, { RFState } from './store';
import { buildDslComponentsByGraph } from './utils';
@ -43,6 +55,32 @@ export const useSelectCanvasData = () => {
return useGraphStore(selector);
};
export const useInitializeOperatorParams = () => {
const llmId = useFetchModelId(true);
const initializeOperatorParams = useCallback(
(operatorName: Operator) => {
const initialFormValuesMap = {
[Operator.Begin]: initialBeginValues,
[Operator.Retrieval]: initialRetrievalValues,
[Operator.Generate]: { ...initialGenerateValues, llm_id: llmId },
[Operator.Answer]: {},
[Operator.Categorize]: { ...initialCategorizeValues, llm_id: llmId },
[Operator.Relevant]: { ...initialRelevantValues, llm_id: llmId },
[Operator.RewriteQuestion]: {
...initialRewriteQuestionValues,
llm_id: llmId,
},
[Operator.Message]: initialMessageValues,
};
return initialFormValuesMap[operatorName];
},
[llmId],
);
return initializeOperatorParams;
};
export const useHandleDrag = () => {
const handleDragStart = useCallback(
(operatorId: string) => (ev: React.DragEvent<HTMLDivElement>) => {
@ -59,6 +97,7 @@ export const useHandleDrop = () => {
const addNode = useGraphStore((state) => state.addNode);
const [reactFlowInstance, setReactFlowInstance] =
useState<ReactFlowInstance<any, any>>();
const initializeOperatorParams = useInitializeOperatorParams();
const onDragOver = useCallback((event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
@ -93,6 +132,7 @@ export const useHandleDrop = () => {
data: {
label: `${type}`,
name: humanId(),
form: initializeOperatorParams(type as Operator),
},
sourcePosition: Position.Right,
targetPosition: Position.Left,
@ -100,7 +140,7 @@ export const useHandleDrop = () => {
addNode(newNode);
},
[reactFlowInstance, addNode],
[reactFlowInstance, addNode, initializeOperatorParams],
);
return { onDrop, onDragOver, setReactFlowInstance };
@ -244,7 +284,10 @@ export const useSetLlmSetting = (form?: FormInstance) => {
return pre;
}, {});
const otherValues = settledModelVariableMap[ModelVariableType.Precise];
form?.setFieldsValue({ ...switchBoxValues, ...otherValues });
form?.setFieldsValue({
...switchBoxValues,
...otherValues,
});
}, [form, initialLlmSetting]);
};

View File

@ -56,6 +56,6 @@
}
.templatesBox {
max-height: 500px;
// max-height: 500px;
overflow: auto;
}

View File

@ -2,11 +2,11 @@ import { DSLComponents } from '@/interfaces/database/flow';
import { removeUselessFieldsFromValues } from '@/utils/form';
import dagre from 'dagre';
import { humanId } from 'human-id';
import { curry, isEmpty } from 'lodash';
import { curry } from 'lodash';
import pipe from 'lodash/fp/pipe';
import { Edge, Node, Position } from 'reactflow';
import { v4 as uuidv4 } from 'uuid';
import { NodeMap, Operator, initialFormValuesMap } from './constant';
import { NodeMap, Operator } from './constant';
import { ICategorizeItemResult, NodeData } from './interface';
const buildEdges = (
@ -143,17 +143,17 @@ const removeUselessDataInTheOperator = curry(
},
);
// initialize data for operators without parameters
const initializeOperatorParams = curry((operatorName: string, values: any) => {
if (isEmpty(values)) {
return initialFormValuesMap[operatorName as Operator];
}
return values;
});
// const initializeOperatorParams = curry((operatorName: string, values: any) => {
// if (isEmpty(values)) {
// return initialFormValuesMap[operatorName as Operator];
// }
// return values;
// });
const buildOperatorParams = (operatorName: string) =>
pipe(
removeUselessDataInTheOperator(operatorName),
initializeOperatorParams(operatorName), // Final processing, for guarantee
// initializeOperatorParams(operatorName), // Final processing, for guarantee
);
// construct a dsl based on the node information of the graph