balibabu
		
	commited on
		
		
					Commit 
							
							·
						
						058cd84
	
1
								Parent(s):
							
							cdba7f7
								
feat: fetch conversation and delete chat dialog (#69)
Browse files* feat: set chat configuration to backend
* feat: exclude unEnabled variables
* feat: delete chat dialog
* feat: fetch conversation
- web/src/constants/chat.ts +4 -0
- web/src/hooks/commonHooks.ts +34 -0
- web/src/hooks/knowledgeHook.ts +9 -2
- web/src/interfaces/database/chat.ts +19 -0
- web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx +1 -3
- web/src/pages/chat/chat-configuration-modal/assistant-setting.tsx +2 -4
- web/src/pages/chat/chat-configuration-modal/index.tsx +39 -10
- web/src/pages/chat/chat-configuration-modal/model-setting.tsx +2 -2
- web/src/pages/chat/chat-configuration-modal/prompt-engine.tsx +15 -17
- web/src/pages/chat/chat-container/index.less +15 -0
- web/src/pages/chat/chat-container/index.tsx +34 -2
- web/src/pages/chat/{chat-configuration-modal/constants.ts → constants.ts} +7 -0
- web/src/pages/chat/hooks.ts +339 -3
- web/src/pages/chat/index.less +23 -0
- web/src/pages/chat/index.tsx +108 -56
- web/src/pages/chat/{chat-configuration-modal/interface.ts → interface.ts} +17 -0
- web/src/pages/chat/model.ts +82 -1
- web/src/pages/chat/utils.ts +12 -0
- web/src/pages/knowledge/model.ts +1 -1
- web/src/services/chatService.ts +5 -0
- web/src/utils/api.ts +1 -0
    	
        web/src/constants/chat.ts
    ADDED
    
    | @@ -0,0 +1,4 @@ | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            export enum MessageType {
         | 
| 2 | 
            +
              Assistant = 'assistant',
         | 
| 3 | 
            +
              User = 'user',
         | 
| 4 | 
            +
            }
         | 
    	
        web/src/hooks/commonHooks.ts
    ADDED
    
    | @@ -0,0 +1,34 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import isEqual from 'lodash/isEqual';
         | 
| 2 | 
            +
            import { useEffect, useRef, useState } from 'react';
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            export const useSetModalState = () => {
         | 
| 5 | 
            +
              const [visible, setVisible] = useState(false);
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              const showModal = () => {
         | 
| 8 | 
            +
                setVisible(true);
         | 
| 9 | 
            +
              };
         | 
| 10 | 
            +
              const hideModal = () => {
         | 
| 11 | 
            +
                setVisible(false);
         | 
| 12 | 
            +
              };
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              return { visible, showModal, hideModal };
         | 
| 15 | 
            +
            };
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            export const useDeepCompareEffect = (
         | 
| 18 | 
            +
              effect: React.EffectCallback,
         | 
| 19 | 
            +
              deps: React.DependencyList,
         | 
| 20 | 
            +
            ) => {
         | 
| 21 | 
            +
              const ref = useRef<React.DependencyList>();
         | 
| 22 | 
            +
              let callback: ReturnType<React.EffectCallback> = () => {};
         | 
| 23 | 
            +
              if (!isEqual(deps, ref.current)) {
         | 
| 24 | 
            +
                callback = effect();
         | 
| 25 | 
            +
                ref.current = deps;
         | 
| 26 | 
            +
              }
         | 
| 27 | 
            +
              useEffect(() => {
         | 
| 28 | 
            +
                return () => {
         | 
| 29 | 
            +
                  if (callback) {
         | 
| 30 | 
            +
                    callback();
         | 
| 31 | 
            +
                  }
         | 
| 32 | 
            +
                };
         | 
| 33 | 
            +
              }, []);
         | 
| 34 | 
            +
            };
         | 
    	
        web/src/hooks/knowledgeHook.ts
    CHANGED
    
    | @@ -125,11 +125,18 @@ export const useFetchKnowledgeBaseConfiguration = () => { | |
| 125 | 
             
              }, [fetchKnowledgeBaseConfiguration]);
         | 
| 126 | 
             
            };
         | 
| 127 |  | 
| 128 | 
            -
            export const useFetchKnowledgeList = ( | 
|  | |
|  | |
| 129 | 
             
              const dispatch = useDispatch();
         | 
| 130 |  | 
| 131 | 
             
              const knowledgeModel = useSelector((state: any) => state.knowledgeModel);
         | 
| 132 | 
             
              const { data = [] } = knowledgeModel;
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 133 |  | 
| 134 | 
             
              const fetchList = useCallback(() => {
         | 
| 135 | 
             
                dispatch({
         | 
| @@ -141,5 +148,5 @@ export const useFetchKnowledgeList = (): IKnowledge[] => { | |
| 141 | 
             
                fetchList();
         | 
| 142 | 
             
              }, [fetchList]);
         | 
| 143 |  | 
| 144 | 
            -
              return  | 
| 145 | 
             
            };
         | 
|  | |
| 125 | 
             
              }, [fetchKnowledgeBaseConfiguration]);
         | 
| 126 | 
             
            };
         | 
| 127 |  | 
| 128 | 
            +
            export const useFetchKnowledgeList = (
         | 
| 129 | 
            +
              shouldFilterListWithoutDocument: boolean = false,
         | 
| 130 | 
            +
            ): IKnowledge[] => {
         | 
| 131 | 
             
              const dispatch = useDispatch();
         | 
| 132 |  | 
| 133 | 
             
              const knowledgeModel = useSelector((state: any) => state.knowledgeModel);
         | 
| 134 | 
             
              const { data = [] } = knowledgeModel;
         | 
| 135 | 
            +
              const list = useMemo(() => {
         | 
| 136 | 
            +
                return shouldFilterListWithoutDocument
         | 
| 137 | 
            +
                  ? data.filter((x: IKnowledge) => x.doc_num > 0)
         | 
| 138 | 
            +
                  : data;
         | 
| 139 | 
            +
              }, [data, shouldFilterListWithoutDocument]);
         | 
| 140 |  | 
| 141 | 
             
              const fetchList = useCallback(() => {
         | 
| 142 | 
             
                dispatch({
         | 
|  | |
| 148 | 
             
                fetchList();
         | 
| 149 | 
             
              }, [fetchList]);
         | 
| 150 |  | 
| 151 | 
            +
              return list;
         | 
| 152 | 
             
            };
         | 
    	
        web/src/interfaces/database/chat.ts
    CHANGED
    
    | @@ -1,3 +1,5 @@ | |
|  | |
|  | |
| 1 | 
             
            export interface PromptConfig {
         | 
| 2 | 
             
              empty_response: string;
         | 
| 3 | 
             
              parameters: Parameter[];
         | 
| @@ -45,3 +47,20 @@ export interface IDialog { | |
| 45 | 
             
              update_date: string;
         | 
| 46 | 
             
              update_time: number;
         | 
| 47 | 
             
            }
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import { MessageType } from '@/constants/chat';
         | 
| 2 | 
            +
             | 
| 3 | 
             
            export interface PromptConfig {
         | 
| 4 | 
             
              empty_response: string;
         | 
| 5 | 
             
              parameters: Parameter[];
         | 
|  | |
| 47 | 
             
              update_date: string;
         | 
| 48 | 
             
              update_time: number;
         | 
| 49 | 
             
            }
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            export interface IConversation {
         | 
| 52 | 
            +
              create_date: string;
         | 
| 53 | 
            +
              create_time: number;
         | 
| 54 | 
            +
              dialog_id: string;
         | 
| 55 | 
            +
              id: string;
         | 
| 56 | 
            +
              message: Message[];
         | 
| 57 | 
            +
              reference: any[];
         | 
| 58 | 
            +
              name: string;
         | 
| 59 | 
            +
              update_date: string;
         | 
| 60 | 
            +
              update_time: number;
         | 
| 61 | 
            +
            }
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            export interface Message {
         | 
| 64 | 
            +
              content: string;
         | 
| 65 | 
            +
              role: MessageType;
         | 
| 66 | 
            +
            }
         | 
    	
        web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx
    CHANGED
    
    | @@ -75,9 +75,7 @@ export const ParsingStatusCell = ({ record }: IProps) => { | |
| 75 |  | 
| 76 | 
             
              return (
         | 
| 77 | 
             
                <Flex justify={'space-between'}>
         | 
| 78 | 
            -
                  <Popover
         | 
| 79 | 
            -
                    content={isRunning && <PopoverContent record={record}></PopoverContent>}
         | 
| 80 | 
            -
                  >
         | 
| 81 | 
             
                    <Tag color={runningStatus.color}>
         | 
| 82 | 
             
                      {isRunning ? (
         | 
| 83 | 
             
                        <Space>
         | 
|  | |
| 75 |  | 
| 76 | 
             
              return (
         | 
| 77 | 
             
                <Flex justify={'space-between'}>
         | 
| 78 | 
            +
                  <Popover content={<PopoverContent record={record}></PopoverContent>}>
         | 
|  | |
|  | |
| 79 | 
             
                    <Tag color={runningStatus.color}>
         | 
| 80 | 
             
                      {isRunning ? (
         | 
| 81 | 
             
                        <Space>
         | 
    	
        web/src/pages/chat/chat-configuration-modal/assistant-setting.tsx
    CHANGED
    
    | @@ -1,15 +1,13 @@ | |
| 1 | 
             
            import { Form, Input, Select } from 'antd';
         | 
| 2 |  | 
| 3 | 
             
            import classNames from 'classnames';
         | 
| 4 | 
            -
            import { ISegmentedContentProps } from ' | 
| 5 |  | 
| 6 | 
             
            import { useFetchKnowledgeList } from '@/hooks/knowledgeHook';
         | 
| 7 | 
             
            import styles from './index.less';
         | 
| 8 |  | 
| 9 | 
            -
            const { Option } = Select;
         | 
| 10 | 
            -
             | 
| 11 | 
             
            const AssistantSetting = ({ show }: ISegmentedContentProps) => {
         | 
| 12 | 
            -
              const knowledgeList = useFetchKnowledgeList();
         | 
| 13 | 
             
              const knowledgeOptions = knowledgeList.map((x) => ({
         | 
| 14 | 
             
                label: x.name,
         | 
| 15 | 
             
                value: x.id,
         | 
|  | |
| 1 | 
             
            import { Form, Input, Select } from 'antd';
         | 
| 2 |  | 
| 3 | 
             
            import classNames from 'classnames';
         | 
| 4 | 
            +
            import { ISegmentedContentProps } from '../interface';
         | 
| 5 |  | 
| 6 | 
             
            import { useFetchKnowledgeList } from '@/hooks/knowledgeHook';
         | 
| 7 | 
             
            import styles from './index.less';
         | 
| 8 |  | 
|  | |
|  | |
| 9 | 
             
            const AssistantSetting = ({ show }: ISegmentedContentProps) => {
         | 
| 10 | 
            +
              const knowledgeList = useFetchKnowledgeList(true);
         | 
| 11 | 
             
              const knowledgeOptions = knowledgeList.map((x) => ({
         | 
| 12 | 
             
                label: x.name,
         | 
| 13 | 
             
                value: x.id,
         | 
    	
        web/src/pages/chat/chat-configuration-modal/index.tsx
    CHANGED
    
    | @@ -3,13 +3,16 @@ import { IModalManagerChildrenProps } from '@/components/modal-manager'; | |
| 3 | 
             
            import { Divider, Flex, Form, Modal, Segmented } from 'antd';
         | 
| 4 | 
             
            import { SegmentedValue } from 'antd/es/segmented';
         | 
| 5 | 
             
            import omit from 'lodash/omit';
         | 
| 6 | 
            -
            import { useRef, useState } from 'react';
         | 
| 7 | 
             
            import AssistantSetting from './assistant-setting';
         | 
| 8 | 
             
            import ModelSetting from './model-setting';
         | 
| 9 | 
             
            import PromptEngine from './prompt-engine';
         | 
| 10 |  | 
| 11 | 
            -
            import {  | 
| 12 | 
            -
            import { variableEnabledFieldMap } from ' | 
|  | |
|  | |
|  | |
| 13 | 
             
            import styles from './index.less';
         | 
| 14 |  | 
| 15 | 
             
            enum ConfigurationSegmented {
         | 
| @@ -40,32 +43,46 @@ const validateMessages = { | |
| 40 | 
             
              },
         | 
| 41 | 
             
            };
         | 
| 42 |  | 
| 43 | 
            -
             | 
| 44 | 
            -
               | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
|  | |
| 47 | 
             
              const [form] = Form.useForm();
         | 
| 48 | 
             
              const [value, setValue] = useState<ConfigurationSegmented>(
         | 
| 49 | 
             
                ConfigurationSegmented.AssistantSetting,
         | 
| 50 | 
             
              );
         | 
| 51 | 
            -
              const promptEngineRef = useRef( | 
|  | |
| 52 |  | 
| 53 | 
             
              const setDialog = useSetDialog();
         | 
|  | |
|  | |
| 54 |  | 
| 55 | 
             
              const handleOk = async () => {
         | 
| 56 | 
             
                const values = await form.validateFields();
         | 
| 57 | 
            -
                const nextValues: any = omit(values,  | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 58 | 
             
                const finalValues = {
         | 
|  | |
| 59 | 
             
                  ...nextValues,
         | 
| 60 | 
             
                  prompt_config: {
         | 
| 61 | 
             
                    ...nextValues.prompt_config,
         | 
| 62 | 
             
                    parameters: promptEngineRef.current,
         | 
|  | |
| 63 | 
             
                  },
         | 
| 64 | 
             
                };
         | 
| 65 | 
             
                console.info(promptEngineRef.current);
         | 
| 66 | 
             
                console.info(nextValues);
         | 
| 67 | 
             
                console.info(finalValues);
         | 
| 68 | 
            -
                setDialog(finalValues);
         | 
|  | |
|  | |
|  | |
| 69 | 
             
              };
         | 
| 70 |  | 
| 71 | 
             
              const handleCancel = () => {
         | 
| @@ -76,6 +93,11 @@ const ChatConfigurationModal = ({ | |
| 76 | 
             
                setValue(val as ConfigurationSegmented);
         | 
| 77 | 
             
              };
         | 
| 78 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 79 | 
             
              const title = (
         | 
| 80 | 
             
                <Flex gap={16}>
         | 
| 81 | 
             
                  <ChatConfigurationAtom></ChatConfigurationAtom>
         | 
| @@ -89,6 +111,10 @@ const ChatConfigurationModal = ({ | |
| 89 | 
             
                </Flex>
         | 
| 90 | 
             
              );
         | 
| 91 |  | 
|  | |
|  | |
|  | |
|  | |
| 92 | 
             
              return (
         | 
| 93 | 
             
                <Modal
         | 
| 94 | 
             
                  title={title}
         | 
| @@ -96,6 +122,9 @@ const ChatConfigurationModal = ({ | |
| 96 | 
             
                  open={visible}
         | 
| 97 | 
             
                  onOk={handleOk}
         | 
| 98 | 
             
                  onCancel={handleCancel}
         | 
|  | |
|  | |
|  | |
| 99 | 
             
                >
         | 
| 100 | 
             
                  <Segmented
         | 
| 101 | 
             
                    size={'large'}
         | 
|  | |
| 3 | 
             
            import { Divider, Flex, Form, Modal, Segmented } from 'antd';
         | 
| 4 | 
             
            import { SegmentedValue } from 'antd/es/segmented';
         | 
| 5 | 
             
            import omit from 'lodash/omit';
         | 
| 6 | 
            +
            import { useEffect, useRef, useState } from 'react';
         | 
| 7 | 
             
            import AssistantSetting from './assistant-setting';
         | 
| 8 | 
             
            import ModelSetting from './model-setting';
         | 
| 9 | 
             
            import PromptEngine from './prompt-engine';
         | 
| 10 |  | 
| 11 | 
            +
            import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
         | 
| 12 | 
            +
            import { variableEnabledFieldMap } from '../constants';
         | 
| 13 | 
            +
            import { useFetchDialog, useResetCurrentDialog, useSetDialog } from '../hooks';
         | 
| 14 | 
            +
            import { IPromptConfigParameters } from '../interface';
         | 
| 15 | 
            +
            import { excludeUnEnabledVariables } from '../utils';
         | 
| 16 | 
             
            import styles from './index.less';
         | 
| 17 |  | 
| 18 | 
             
            enum ConfigurationSegmented {
         | 
|  | |
| 43 | 
             
              },
         | 
| 44 | 
             
            };
         | 
| 45 |  | 
| 46 | 
            +
            interface IProps extends IModalManagerChildrenProps {
         | 
| 47 | 
            +
              id: string;
         | 
| 48 | 
            +
            }
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            const ChatConfigurationModal = ({ visible, hideModal, id }: IProps) => {
         | 
| 51 | 
             
              const [form] = Form.useForm();
         | 
| 52 | 
             
              const [value, setValue] = useState<ConfigurationSegmented>(
         | 
| 53 | 
             
                ConfigurationSegmented.AssistantSetting,
         | 
| 54 | 
             
              );
         | 
| 55 | 
            +
              const promptEngineRef = useRef<Array<IPromptConfigParameters>>([]);
         | 
| 56 | 
            +
              const loading = useOneNamespaceEffectsLoading('chatModel', ['setDialog']);
         | 
| 57 |  | 
| 58 | 
             
              const setDialog = useSetDialog();
         | 
| 59 | 
            +
              const currentDialog = useFetchDialog(id, visible);
         | 
| 60 | 
            +
              const { resetCurrentDialog } = useResetCurrentDialog();
         | 
| 61 |  | 
| 62 | 
             
              const handleOk = async () => {
         | 
| 63 | 
             
                const values = await form.validateFields();
         | 
| 64 | 
            +
                const nextValues: any = omit(values, [
         | 
| 65 | 
            +
                  ...Object.keys(variableEnabledFieldMap),
         | 
| 66 | 
            +
                  'parameters',
         | 
| 67 | 
            +
                  ...excludeUnEnabledVariables(values),
         | 
| 68 | 
            +
                ]);
         | 
| 69 | 
            +
                const emptyResponse = nextValues.prompt_config?.empty_response ?? '';
         | 
| 70 | 
             
                const finalValues = {
         | 
| 71 | 
            +
                  dialog_id: id,
         | 
| 72 | 
             
                  ...nextValues,
         | 
| 73 | 
             
                  prompt_config: {
         | 
| 74 | 
             
                    ...nextValues.prompt_config,
         | 
| 75 | 
             
                    parameters: promptEngineRef.current,
         | 
| 76 | 
            +
                    empty_response: emptyResponse,
         | 
| 77 | 
             
                  },
         | 
| 78 | 
             
                };
         | 
| 79 | 
             
                console.info(promptEngineRef.current);
         | 
| 80 | 
             
                console.info(nextValues);
         | 
| 81 | 
             
                console.info(finalValues);
         | 
| 82 | 
            +
                const retcode: number = await setDialog(finalValues);
         | 
| 83 | 
            +
                if (retcode === 0) {
         | 
| 84 | 
            +
                  hideModal();
         | 
| 85 | 
            +
                }
         | 
| 86 | 
             
              };
         | 
| 87 |  | 
| 88 | 
             
              const handleCancel = () => {
         | 
|  | |
| 93 | 
             
                setValue(val as ConfigurationSegmented);
         | 
| 94 | 
             
              };
         | 
| 95 |  | 
| 96 | 
            +
              const handleModalAfterClose = () => {
         | 
| 97 | 
            +
                resetCurrentDialog();
         | 
| 98 | 
            +
                form.resetFields();
         | 
| 99 | 
            +
              };
         | 
| 100 | 
            +
             | 
| 101 | 
             
              const title = (
         | 
| 102 | 
             
                <Flex gap={16}>
         | 
| 103 | 
             
                  <ChatConfigurationAtom></ChatConfigurationAtom>
         | 
|  | |
| 111 | 
             
                </Flex>
         | 
| 112 | 
             
              );
         | 
| 113 |  | 
| 114 | 
            +
              useEffect(() => {
         | 
| 115 | 
            +
                form.setFieldsValue(currentDialog);
         | 
| 116 | 
            +
              }, [currentDialog, form]);
         | 
| 117 | 
            +
             | 
| 118 | 
             
              return (
         | 
| 119 | 
             
                <Modal
         | 
| 120 | 
             
                  title={title}
         | 
|  | |
| 122 | 
             
                  open={visible}
         | 
| 123 | 
             
                  onOk={handleOk}
         | 
| 124 | 
             
                  onCancel={handleCancel}
         | 
| 125 | 
            +
                  confirmLoading={loading}
         | 
| 126 | 
            +
                  destroyOnClose
         | 
| 127 | 
            +
                  afterClose={handleModalAfterClose}
         | 
| 128 | 
             
                >
         | 
| 129 | 
             
                  <Segmented
         | 
| 130 | 
             
                    size={'large'}
         | 
    	
        web/src/pages/chat/chat-configuration-modal/model-setting.tsx
    CHANGED
    
    | @@ -6,10 +6,10 @@ import { | |
| 6 | 
             
            import { Divider, Flex, Form, InputNumber, Select, Slider, Switch } from 'antd';
         | 
| 7 | 
             
            import classNames from 'classnames';
         | 
| 8 | 
             
            import { useEffect } from 'react';
         | 
| 9 | 
            -
            import { ISegmentedContentProps } from ' | 
| 10 |  | 
| 11 | 
             
            import { useFetchLlmList, useSelectLlmOptions } from '@/hooks/llmHooks';
         | 
| 12 | 
            -
            import { variableEnabledFieldMap } from ' | 
| 13 | 
             
            import styles from './index.less';
         | 
| 14 |  | 
| 15 | 
             
            const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
         | 
|  | |
| 6 | 
             
            import { Divider, Flex, Form, InputNumber, Select, Slider, Switch } from 'antd';
         | 
| 7 | 
             
            import classNames from 'classnames';
         | 
| 8 | 
             
            import { useEffect } from 'react';
         | 
| 9 | 
            +
            import { ISegmentedContentProps } from '../interface';
         | 
| 10 |  | 
| 11 | 
             
            import { useFetchLlmList, useSelectLlmOptions } from '@/hooks/llmHooks';
         | 
| 12 | 
            +
            import { variableEnabledFieldMap } from '../constants';
         | 
| 13 | 
             
            import styles from './index.less';
         | 
| 14 |  | 
| 15 | 
             
            const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
         | 
    	
        web/src/pages/chat/chat-configuration-modal/prompt-engine.tsx
    CHANGED
    
    | @@ -21,17 +21,16 @@ import { | |
| 21 | 
             
              useState,
         | 
| 22 | 
             
            } from 'react';
         | 
| 23 | 
             
            import { v4 as uuid } from 'uuid';
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 24 | 
             
            import { EditableCell, EditableRow } from './editable-cell';
         | 
| 25 | 
            -
            import { ISegmentedContentProps } from './interface';
         | 
| 26 |  | 
|  | |
| 27 | 
             
            import styles from './index.less';
         | 
| 28 |  | 
| 29 | 
            -
            interface DataType {
         | 
| 30 | 
            -
              key: string;
         | 
| 31 | 
            -
              variable: string;
         | 
| 32 | 
            -
              optional: boolean;
         | 
| 33 | 
            -
            }
         | 
| 34 | 
            -
             | 
| 35 | 
             
            type FieldType = {
         | 
| 36 | 
             
              similarity_threshold?: number;
         | 
| 37 | 
             
              vector_similarity_weight?: number;
         | 
| @@ -39,10 +38,11 @@ type FieldType = { | |
| 39 | 
             
            };
         | 
| 40 |  | 
| 41 | 
             
            const PromptEngine = (
         | 
| 42 | 
            -
              { show | 
| 43 | 
            -
              ref: ForwardedRef<Array< | 
| 44 | 
             
            ) => {
         | 
| 45 | 
             
              const [dataSource, setDataSource] = useState<DataType[]>([]);
         | 
|  | |
| 46 |  | 
| 47 | 
             
              const components = {
         | 
| 48 | 
             
                body: {
         | 
| @@ -99,12 +99,6 @@ const PromptEngine = ( | |
| 99 | 
             
                [dataSource],
         | 
| 100 | 
             
              );
         | 
| 101 |  | 
| 102 | 
            -
              useEffect(() => {
         | 
| 103 | 
            -
                form.setFieldValue(['prompt_config', 'parameters'], dataSource);
         | 
| 104 | 
            -
                const x = form.getFieldValue(['prompt_config', 'parameters']);
         | 
| 105 | 
            -
                console.info(x);
         | 
| 106 | 
            -
              }, [dataSource, form]);
         | 
| 107 | 
            -
             | 
| 108 | 
             
              const columns: TableProps<DataType>['columns'] = [
         | 
| 109 | 
             
                {
         | 
| 110 | 
             
                  title: 'key',
         | 
| @@ -146,6 +140,10 @@ const PromptEngine = ( | |
| 146 | 
             
                },
         | 
| 147 | 
             
              ];
         | 
| 148 |  | 
|  | |
|  | |
|  | |
|  | |
| 149 | 
             
              return (
         | 
| 150 | 
             
                <section
         | 
| 151 | 
             
                  className={classNames({
         | 
| @@ -153,7 +151,7 @@ const PromptEngine = ( | |
| 153 | 
             
                  })}
         | 
| 154 | 
             
                >
         | 
| 155 | 
             
                  <Form.Item
         | 
| 156 | 
            -
                    label=" | 
| 157 | 
             
                    rules={[{ required: true, message: 'Please input!' }]}
         | 
| 158 | 
             
                    name={['prompt_config', 'system']}
         | 
| 159 | 
             
                    initialValue={`你是一个智能助手,请总结知识库的内容来回答问题,请列举知识库中的数据详细回答。当所有知识库内容都与问题无关时,你的回答必须包括“知识库中未找到您要的答案!”这句话。回答需要考虑聊天历史。
         | 
| @@ -161,7 +159,7 @@ const PromptEngine = ( | |
| 161 | 
             
                    {knowledge}
         | 
| 162 | 
             
                    以上是知识库。`}
         | 
| 163 | 
             
                  >
         | 
| 164 | 
            -
                    <Input.TextArea autoSize={{ maxRows:  | 
| 165 | 
             
                  </Form.Item>
         | 
| 166 | 
             
                  <Divider></Divider>
         | 
| 167 | 
             
                  <SimilaritySlider></SimilaritySlider>
         | 
|  | |
| 21 | 
             
              useState,
         | 
| 22 | 
             
            } from 'react';
         | 
| 23 | 
             
            import { v4 as uuid } from 'uuid';
         | 
| 24 | 
            +
            import {
         | 
| 25 | 
            +
              VariableTableDataType as DataType,
         | 
| 26 | 
            +
              IPromptConfigParameters,
         | 
| 27 | 
            +
              ISegmentedContentProps,
         | 
| 28 | 
            +
            } from '../interface';
         | 
| 29 | 
             
            import { EditableCell, EditableRow } from './editable-cell';
         | 
|  | |
| 30 |  | 
| 31 | 
            +
            import { useSelectPromptConfigParameters } from '../hooks';
         | 
| 32 | 
             
            import styles from './index.less';
         | 
| 33 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 34 | 
             
            type FieldType = {
         | 
| 35 | 
             
              similarity_threshold?: number;
         | 
| 36 | 
             
              vector_similarity_weight?: number;
         | 
|  | |
| 38 | 
             
            };
         | 
| 39 |  | 
| 40 | 
             
            const PromptEngine = (
         | 
| 41 | 
            +
              { show }: ISegmentedContentProps,
         | 
| 42 | 
            +
              ref: ForwardedRef<Array<IPromptConfigParameters>>,
         | 
| 43 | 
             
            ) => {
         | 
| 44 | 
             
              const [dataSource, setDataSource] = useState<DataType[]>([]);
         | 
| 45 | 
            +
              const parameters = useSelectPromptConfigParameters();
         | 
| 46 |  | 
| 47 | 
             
              const components = {
         | 
| 48 | 
             
                body: {
         | 
|  | |
| 99 | 
             
                [dataSource],
         | 
| 100 | 
             
              );
         | 
| 101 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 102 | 
             
              const columns: TableProps<DataType>['columns'] = [
         | 
| 103 | 
             
                {
         | 
| 104 | 
             
                  title: 'key',
         | 
|  | |
| 140 | 
             
                },
         | 
| 141 | 
             
              ];
         | 
| 142 |  | 
| 143 | 
            +
              useEffect(() => {
         | 
| 144 | 
            +
                setDataSource(parameters);
         | 
| 145 | 
            +
              }, [parameters]);
         | 
| 146 | 
            +
             | 
| 147 | 
             
              return (
         | 
| 148 | 
             
                <section
         | 
| 149 | 
             
                  className={classNames({
         | 
|  | |
| 151 | 
             
                  })}
         | 
| 152 | 
             
                >
         | 
| 153 | 
             
                  <Form.Item
         | 
| 154 | 
            +
                    label="System"
         | 
| 155 | 
             
                    rules={[{ required: true, message: 'Please input!' }]}
         | 
| 156 | 
             
                    name={['prompt_config', 'system']}
         | 
| 157 | 
             
                    initialValue={`你是一个智能助手,请总结知识库的内容来回答问题,请列举知识库中的数据详细回答。当所有知识库内容都与问题无关时,你的回答必须包括“知识库中未找到您要的答案!”这句话。回答需要考虑聊天历史。
         | 
|  | |
| 159 | 
             
                    {knowledge}
         | 
| 160 | 
             
                    以上是知识库。`}
         | 
| 161 | 
             
                  >
         | 
| 162 | 
            +
                    <Input.TextArea autoSize={{ maxRows: 8, minRows: 5 }} />
         | 
| 163 | 
             
                  </Form.Item>
         | 
| 164 | 
             
                  <Divider></Divider>
         | 
| 165 | 
             
                  <SimilaritySlider></SimilaritySlider>
         | 
    	
        web/src/pages/chat/chat-container/index.less
    CHANGED
    
    | @@ -1,3 +1,18 @@ | |
| 1 | 
             
            .chatContainer {
         | 
| 2 | 
             
              padding: 0 24px 24px;
         | 
| 3 | 
             
            }
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
             
            .chatContainer {
         | 
| 2 | 
             
              padding: 0 24px 24px;
         | 
| 3 | 
             
            }
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            .messageItem {
         | 
| 6 | 
            +
              .messageItemContent {
         | 
| 7 | 
            +
                display: inline-block;
         | 
| 8 | 
            +
                width: 300px;
         | 
| 9 | 
            +
              }
         | 
| 10 | 
            +
            }
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            .messageItemLeft {
         | 
| 13 | 
            +
              text-align: left;
         | 
| 14 | 
            +
            }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            .messageItemRight {
         | 
| 17 | 
            +
              text-align: right;
         | 
| 18 | 
            +
            }
         | 
    	
        web/src/pages/chat/chat-container/index.tsx
    CHANGED
    
    | @@ -1,13 +1,41 @@ | |
| 1 | 
            -
            import { Button, Flex, Input } from 'antd';
         | 
| 2 | 
             
            import { ChangeEventHandler, useState } from 'react';
         | 
| 3 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 4 | 
             
            import styles from './index.less';
         | 
| 5 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 6 | 
             
            const ChatContainer = () => {
         | 
| 7 | 
             
              const [value, setValue] = useState('');
         | 
|  | |
|  | |
| 8 |  | 
| 9 | 
             
              const handlePressEnter = () => {
         | 
| 10 | 
             
                console.info(value);
         | 
|  | |
| 11 | 
             
              };
         | 
| 12 |  | 
| 13 | 
             
              const handleInputChange: ChangeEventHandler<HTMLInputElement> = (e) => {
         | 
| @@ -16,7 +44,11 @@ const ChatContainer = () => { | |
| 16 |  | 
| 17 | 
             
              return (
         | 
| 18 | 
             
                <Flex flex={1} className={styles.chatContainer} vertical>
         | 
| 19 | 
            -
                  <Flex flex={1}> | 
|  | |
|  | |
|  | |
|  | |
| 20 | 
             
                  <Input
         | 
| 21 | 
             
                    size="large"
         | 
| 22 | 
             
                    placeholder="Message Resume Assistant..."
         | 
|  | |
| 1 | 
            +
            import { Button, Flex, Input, Typography } from 'antd';
         | 
| 2 | 
             
            import { ChangeEventHandler, useState } from 'react';
         | 
| 3 |  | 
| 4 | 
            +
            import { Message } from '@/interfaces/database/chat';
         | 
| 5 | 
            +
            import classNames from 'classnames';
         | 
| 6 | 
            +
            import { useFetchConversation, useSendMessage } from '../hooks';
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            import { MessageType } from '@/constants/chat';
         | 
| 9 | 
            +
            import { IClientConversation } from '../interface';
         | 
| 10 | 
             
            import styles from './index.less';
         | 
| 11 |  | 
| 12 | 
            +
            const { Paragraph } = Typography;
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            const MessageItem = ({ item }: { item: Message }) => {
         | 
| 15 | 
            +
              return (
         | 
| 16 | 
            +
                <div
         | 
| 17 | 
            +
                  className={classNames(styles.messageItem, {
         | 
| 18 | 
            +
                    [styles.messageItemLeft]: item.role === MessageType.Assistant,
         | 
| 19 | 
            +
                    [styles.messageItemRight]: item.role === MessageType.User,
         | 
| 20 | 
            +
                  })}
         | 
| 21 | 
            +
                >
         | 
| 22 | 
            +
                  <span className={styles.messageItemContent}>
         | 
| 23 | 
            +
                    <Paragraph ellipsis={{ tooltip: item.content, rows: 3 }}>
         | 
| 24 | 
            +
                      {item.content}
         | 
| 25 | 
            +
                    </Paragraph>
         | 
| 26 | 
            +
                  </span>
         | 
| 27 | 
            +
                </div>
         | 
| 28 | 
            +
              );
         | 
| 29 | 
            +
            };
         | 
| 30 | 
            +
             | 
| 31 | 
             
            const ChatContainer = () => {
         | 
| 32 | 
             
              const [value, setValue] = useState('');
         | 
| 33 | 
            +
              const conversation: IClientConversation = useFetchConversation();
         | 
| 34 | 
            +
              const { sendMessage } = useSendMessage();
         | 
| 35 |  | 
| 36 | 
             
              const handlePressEnter = () => {
         | 
| 37 | 
             
                console.info(value);
         | 
| 38 | 
            +
                sendMessage(value);
         | 
| 39 | 
             
              };
         | 
| 40 |  | 
| 41 | 
             
              const handleInputChange: ChangeEventHandler<HTMLInputElement> = (e) => {
         | 
|  | |
| 44 |  | 
| 45 | 
             
              return (
         | 
| 46 | 
             
                <Flex flex={1} className={styles.chatContainer} vertical>
         | 
| 47 | 
            +
                  <Flex flex={1} vertical>
         | 
| 48 | 
            +
                    {conversation?.message?.map((message) => (
         | 
| 49 | 
            +
                      <MessageItem key={message.id} item={message}></MessageItem>
         | 
| 50 | 
            +
                    ))}
         | 
| 51 | 
            +
                  </Flex>
         | 
| 52 | 
             
                  <Input
         | 
| 53 | 
             
                    size="large"
         | 
| 54 | 
             
                    placeholder="Message Resume Assistant..."
         | 
    	
        web/src/pages/chat/{chat-configuration-modal/constants.ts → constants.ts}
    RENAMED
    
    | @@ -5,3 +5,10 @@ export const variableEnabledFieldMap = { | |
| 5 | 
             
              frequencyPenaltyEnabled: 'frequency_penalty',
         | 
| 6 | 
             
              maxTokensEnabled: 'max_tokens',
         | 
| 7 | 
             
            };
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 5 | 
             
              frequencyPenaltyEnabled: 'frequency_penalty',
         | 
| 6 | 
             
              maxTokensEnabled: 'max_tokens',
         | 
| 7 | 
             
            };
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            export enum ChatSearchParams {
         | 
| 10 | 
            +
              DialogId = 'dialogId',
         | 
| 11 | 
            +
              ConversationId = 'conversationId',
         | 
| 12 | 
            +
            }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            export const EmptyConversationId = 'empty';
         | 
    	
        web/src/pages/chat/hooks.ts
    CHANGED
    
    | @@ -1,6 +1,16 @@ | |
|  | |
|  | |
| 1 | 
             
            import { IDialog } from '@/interfaces/database/chat';
         | 
| 2 | 
            -
            import  | 
| 3 | 
            -
            import {  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 4 |  | 
| 5 | 
             
            export const useFetchDialogList = () => {
         | 
| 6 | 
             
              const dispatch = useDispatch();
         | 
| @@ -20,10 +30,336 @@ export const useSetDialog = () => { | |
| 20 |  | 
| 21 | 
             
              const setDialog = useCallback(
         | 
| 22 | 
             
                (payload: IDialog) => {
         | 
| 23 | 
            -
                  dispatch({ type: 'chatModel/setDialog', payload });
         | 
| 24 | 
             
                },
         | 
| 25 | 
             
                [dispatch],
         | 
| 26 | 
             
              );
         | 
| 27 |  | 
| 28 | 
             
              return setDialog;
         | 
| 29 | 
             
            };
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import showDeleteConfirm from '@/components/deleting-confirm';
         | 
| 2 | 
            +
            import { MessageType } from '@/constants/chat';
         | 
| 3 | 
             
            import { IDialog } from '@/interfaces/database/chat';
         | 
| 4 | 
            +
            import omit from 'lodash/omit';
         | 
| 5 | 
            +
            import { useCallback, useEffect, useMemo } from 'react';
         | 
| 6 | 
            +
            import { useDispatch, useSearchParams, useSelector } from 'umi';
         | 
| 7 | 
            +
            import { v4 as uuid } from 'uuid';
         | 
| 8 | 
            +
            import { ChatSearchParams, EmptyConversationId } from './constants';
         | 
| 9 | 
            +
            import {
         | 
| 10 | 
            +
              IClientConversation,
         | 
| 11 | 
            +
              IMessage,
         | 
| 12 | 
            +
              VariableTableDataType,
         | 
| 13 | 
            +
            } from './interface';
         | 
| 14 |  | 
| 15 | 
             
            export const useFetchDialogList = () => {
         | 
| 16 | 
             
              const dispatch = useDispatch();
         | 
|  | |
| 30 |  | 
| 31 | 
             
              const setDialog = useCallback(
         | 
| 32 | 
             
                (payload: IDialog) => {
         | 
| 33 | 
            +
                  return dispatch<any>({ type: 'chatModel/setDialog', payload });
         | 
| 34 | 
             
                },
         | 
| 35 | 
             
                [dispatch],
         | 
| 36 | 
             
              );
         | 
| 37 |  | 
| 38 | 
             
              return setDialog;
         | 
| 39 | 
             
            };
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            export const useFetchDialog = (dialogId: string, visible: boolean): IDialog => {
         | 
| 42 | 
            +
              const dispatch = useDispatch();
         | 
| 43 | 
            +
              const currentDialog: IDialog = useSelector(
         | 
| 44 | 
            +
                (state: any) => state.chatModel.currentDialog,
         | 
| 45 | 
            +
              );
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              const fetchDialog = useCallback(() => {
         | 
| 48 | 
            +
                if (dialogId) {
         | 
| 49 | 
            +
                  dispatch({
         | 
| 50 | 
            +
                    type: 'chatModel/getDialog',
         | 
| 51 | 
            +
                    payload: { dialog_id: dialogId },
         | 
| 52 | 
            +
                  });
         | 
| 53 | 
            +
                }
         | 
| 54 | 
            +
              }, [dispatch, dialogId]);
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              useEffect(() => {
         | 
| 57 | 
            +
                if (dialogId && visible) {
         | 
| 58 | 
            +
                  fetchDialog();
         | 
| 59 | 
            +
                }
         | 
| 60 | 
            +
              }, [dialogId, fetchDialog, visible]);
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              return currentDialog;
         | 
| 63 | 
            +
            };
         | 
| 64 | 
            +
             | 
| 65 | 
            +
            export const useSetCurrentDialog = () => {
         | 
| 66 | 
            +
              const dispatch = useDispatch();
         | 
| 67 | 
            +
             | 
| 68 | 
            +
              const currentDialog: IDialog = useSelector(
         | 
| 69 | 
            +
                (state: any) => state.chatModel.currentDialog,
         | 
| 70 | 
            +
              );
         | 
| 71 | 
            +
             | 
| 72 | 
            +
              const setCurrentDialog = useCallback(
         | 
| 73 | 
            +
                (dialogId: string) => {
         | 
| 74 | 
            +
                  if (dialogId) {
         | 
| 75 | 
            +
                    dispatch({
         | 
| 76 | 
            +
                      type: 'chatModel/setCurrentDialog',
         | 
| 77 | 
            +
                      payload: { id: dialogId },
         | 
| 78 | 
            +
                    });
         | 
| 79 | 
            +
                  }
         | 
| 80 | 
            +
                },
         | 
| 81 | 
            +
                [dispatch],
         | 
| 82 | 
            +
              );
         | 
| 83 | 
            +
             | 
| 84 | 
            +
              return { currentDialog, setCurrentDialog };
         | 
| 85 | 
            +
            };
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            export const useResetCurrentDialog = () => {
         | 
| 88 | 
            +
              const dispatch = useDispatch();
         | 
| 89 | 
            +
             | 
| 90 | 
            +
              const resetCurrentDialog = useCallback(() => {
         | 
| 91 | 
            +
                dispatch({
         | 
| 92 | 
            +
                  type: 'chatModel/setCurrentDialog',
         | 
| 93 | 
            +
                  payload: {},
         | 
| 94 | 
            +
                });
         | 
| 95 | 
            +
              }, [dispatch]);
         | 
| 96 | 
            +
             | 
| 97 | 
            +
              return { resetCurrentDialog };
         | 
| 98 | 
            +
            };
         | 
| 99 | 
            +
             | 
| 100 | 
            +
            export const useSelectPromptConfigParameters = (): VariableTableDataType[] => {
         | 
| 101 | 
            +
              const currentDialog: IDialog = useSelector(
         | 
| 102 | 
            +
                (state: any) => state.chatModel.currentDialog,
         | 
| 103 | 
            +
              );
         | 
| 104 | 
            +
             | 
| 105 | 
            +
              const finalParameters: VariableTableDataType[] = useMemo(() => {
         | 
| 106 | 
            +
                const parameters = currentDialog?.prompt_config?.parameters ?? [];
         | 
| 107 | 
            +
                if (!currentDialog.id) {
         | 
| 108 | 
            +
                  // The newly created chat has a default parameter
         | 
| 109 | 
            +
                  return [{ key: uuid(), variable: 'knowledge', optional: false }];
         | 
| 110 | 
            +
                }
         | 
| 111 | 
            +
                return parameters.map((x) => ({
         | 
| 112 | 
            +
                  key: uuid(),
         | 
| 113 | 
            +
                  variable: x.key,
         | 
| 114 | 
            +
                  optional: x.optional,
         | 
| 115 | 
            +
                }));
         | 
| 116 | 
            +
              }, [currentDialog]);
         | 
| 117 | 
            +
             | 
| 118 | 
            +
              return finalParameters;
         | 
| 119 | 
            +
            };
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            export const useRemoveDialog = () => {
         | 
| 122 | 
            +
              const dispatch = useDispatch();
         | 
| 123 | 
            +
             | 
| 124 | 
            +
              const removeDocument = (dialogIds: Array<string>) => () => {
         | 
| 125 | 
            +
                return dispatch({
         | 
| 126 | 
            +
                  type: 'chatModel/removeDialog',
         | 
| 127 | 
            +
                  payload: {
         | 
| 128 | 
            +
                    dialog_ids: dialogIds,
         | 
| 129 | 
            +
                  },
         | 
| 130 | 
            +
                });
         | 
| 131 | 
            +
              };
         | 
| 132 | 
            +
             | 
| 133 | 
            +
              const onRemoveDialog = (dialogIds: Array<string>) => {
         | 
| 134 | 
            +
                showDeleteConfirm({ onOk: removeDocument(dialogIds) });
         | 
| 135 | 
            +
              };
         | 
| 136 | 
            +
             | 
| 137 | 
            +
              return { onRemoveDialog };
         | 
| 138 | 
            +
            };
         | 
| 139 | 
            +
             | 
| 140 | 
            +
            export const useClickDialogCard = () => {
         | 
| 141 | 
            +
              const [currentQueryParameters, setSearchParams] = useSearchParams();
         | 
| 142 | 
            +
             | 
| 143 | 
            +
              const newQueryParameters: URLSearchParams = useMemo(() => {
         | 
| 144 | 
            +
                return new URLSearchParams(currentQueryParameters.toString());
         | 
| 145 | 
            +
              }, [currentQueryParameters]);
         | 
| 146 | 
            +
             | 
| 147 | 
            +
              const handleClickDialog = useCallback(
         | 
| 148 | 
            +
                (dialogId: string) => {
         | 
| 149 | 
            +
                  newQueryParameters.set(ChatSearchParams.DialogId, dialogId);
         | 
| 150 | 
            +
                  setSearchParams(newQueryParameters);
         | 
| 151 | 
            +
                },
         | 
| 152 | 
            +
                [newQueryParameters, setSearchParams],
         | 
| 153 | 
            +
              );
         | 
| 154 | 
            +
             | 
| 155 | 
            +
              return { handleClickDialog };
         | 
| 156 | 
            +
            };
         | 
| 157 | 
            +
             | 
| 158 | 
            +
            export const useGetChatSearchParams = () => {
         | 
| 159 | 
            +
              const [currentQueryParameters] = useSearchParams();
         | 
| 160 | 
            +
             | 
| 161 | 
            +
              return {
         | 
| 162 | 
            +
                dialogId: currentQueryParameters.get(ChatSearchParams.DialogId) || '',
         | 
| 163 | 
            +
                conversationId:
         | 
| 164 | 
            +
                  currentQueryParameters.get(ChatSearchParams.ConversationId) || '',
         | 
| 165 | 
            +
              };
         | 
| 166 | 
            +
            };
         | 
| 167 | 
            +
             | 
| 168 | 
            +
            export const useSelectFirstDialogOnMount = () => {
         | 
| 169 | 
            +
              const dialogList = useFetchDialogList();
         | 
| 170 | 
            +
              const { dialogId } = useGetChatSearchParams();
         | 
| 171 | 
            +
             | 
| 172 | 
            +
              const { handleClickDialog } = useClickDialogCard();
         | 
| 173 | 
            +
             | 
| 174 | 
            +
              useEffect(() => {
         | 
| 175 | 
            +
                if (dialogList.length > 0 && !dialogId) {
         | 
| 176 | 
            +
                  handleClickDialog(dialogList[0].id);
         | 
| 177 | 
            +
                }
         | 
| 178 | 
            +
              }, [dialogList, handleClickDialog, dialogId]);
         | 
| 179 | 
            +
             | 
| 180 | 
            +
              return dialogList;
         | 
| 181 | 
            +
            };
         | 
| 182 | 
            +
             | 
| 183 | 
            +
            //#region conversation
         | 
| 184 | 
            +
             | 
| 185 | 
            +
            export const useFetchConversationList = (dialogId?: string) => {
         | 
| 186 | 
            +
              const dispatch = useDispatch();
         | 
| 187 | 
            +
              const conversationList: any[] = useSelector(
         | 
| 188 | 
            +
                (state: any) => state.chatModel.conversationList,
         | 
| 189 | 
            +
              );
         | 
| 190 | 
            +
             | 
| 191 | 
            +
              const fetchConversationList = useCallback(() => {
         | 
| 192 | 
            +
                if (dialogId) {
         | 
| 193 | 
            +
                  dispatch({
         | 
| 194 | 
            +
                    type: 'chatModel/listConversation',
         | 
| 195 | 
            +
                    payload: { dialog_id: dialogId },
         | 
| 196 | 
            +
                  });
         | 
| 197 | 
            +
                }
         | 
| 198 | 
            +
              }, [dispatch, dialogId]);
         | 
| 199 | 
            +
             | 
| 200 | 
            +
              useEffect(() => {
         | 
| 201 | 
            +
                fetchConversationList();
         | 
| 202 | 
            +
              }, [fetchConversationList]);
         | 
| 203 | 
            +
             | 
| 204 | 
            +
              return conversationList;
         | 
| 205 | 
            +
            };
         | 
| 206 | 
            +
             | 
| 207 | 
            +
            export const useClickConversationCard = () => {
         | 
| 208 | 
            +
              const [currentQueryParameters, setSearchParams] = useSearchParams();
         | 
| 209 | 
            +
              const newQueryParameters: URLSearchParams = new URLSearchParams(
         | 
| 210 | 
            +
                currentQueryParameters.toString(),
         | 
| 211 | 
            +
              );
         | 
| 212 | 
            +
             | 
| 213 | 
            +
              const handleClickConversation = (conversationId: string) => {
         | 
| 214 | 
            +
                newQueryParameters.set(ChatSearchParams.ConversationId, conversationId);
         | 
| 215 | 
            +
                setSearchParams(newQueryParameters);
         | 
| 216 | 
            +
              };
         | 
| 217 | 
            +
             | 
| 218 | 
            +
              return { handleClickConversation };
         | 
| 219 | 
            +
            };
         | 
| 220 | 
            +
             | 
| 221 | 
            +
            export const useCreateTemporaryConversation = () => {
         | 
| 222 | 
            +
              const dispatch = useDispatch();
         | 
| 223 | 
            +
              const { dialogId } = useGetChatSearchParams();
         | 
| 224 | 
            +
              const { handleClickConversation } = useClickConversationCard();
         | 
| 225 | 
            +
              let chatModel = useSelector((state: any) => state.chatModel);
         | 
| 226 | 
            +
              let currentConversation: Pick<
         | 
| 227 | 
            +
                IClientConversation,
         | 
| 228 | 
            +
                'id' | 'message' | 'name' | 'dialog_id'
         | 
| 229 | 
            +
              > = chatModel.currentConversation;
         | 
| 230 | 
            +
              let conversationList: IClientConversation[] = chatModel.conversationList;
         | 
| 231 | 
            +
             | 
| 232 | 
            +
              const createTemporaryConversation = (message: string) => {
         | 
| 233 | 
            +
                const messages = [...(currentConversation?.message ?? [])];
         | 
| 234 | 
            +
                if (messages.some((x) => x.id === EmptyConversationId)) {
         | 
| 235 | 
            +
                  return;
         | 
| 236 | 
            +
                }
         | 
| 237 | 
            +
                messages.unshift({
         | 
| 238 | 
            +
                  id: EmptyConversationId,
         | 
| 239 | 
            +
                  content: message,
         | 
| 240 | 
            +
                  role: MessageType.Assistant,
         | 
| 241 | 
            +
                });
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                // It’s the back-end data.
         | 
| 244 | 
            +
                if ('id' in currentConversation) {
         | 
| 245 | 
            +
                  currentConversation = { ...currentConversation, message: messages };
         | 
| 246 | 
            +
                } else {
         | 
| 247 | 
            +
                  // client data
         | 
| 248 | 
            +
                  currentConversation = {
         | 
| 249 | 
            +
                    id: EmptyConversationId,
         | 
| 250 | 
            +
                    name: 'New conversation',
         | 
| 251 | 
            +
                    dialog_id: dialogId,
         | 
| 252 | 
            +
                    message: messages,
         | 
| 253 | 
            +
                  };
         | 
| 254 | 
            +
                }
         | 
| 255 | 
            +
             | 
| 256 | 
            +
                const nextConversationList = [...conversationList];
         | 
| 257 | 
            +
             | 
| 258 | 
            +
                nextConversationList.push(currentConversation as IClientConversation);
         | 
| 259 | 
            +
             | 
| 260 | 
            +
                dispatch({
         | 
| 261 | 
            +
                  type: 'chatModel/setCurrentConversation',
         | 
| 262 | 
            +
                  payload: currentConversation,
         | 
| 263 | 
            +
                });
         | 
| 264 | 
            +
             | 
| 265 | 
            +
                dispatch({
         | 
| 266 | 
            +
                  type: 'chatModel/setConversationList',
         | 
| 267 | 
            +
                  payload: nextConversationList,
         | 
| 268 | 
            +
                });
         | 
| 269 | 
            +
                handleClickConversation(EmptyConversationId);
         | 
| 270 | 
            +
              };
         | 
| 271 | 
            +
             | 
| 272 | 
            +
              return { createTemporaryConversation };
         | 
| 273 | 
            +
            };
         | 
| 274 | 
            +
             | 
| 275 | 
            +
            export const useSetConversation = () => {
         | 
| 276 | 
            +
              const dispatch = useDispatch();
         | 
| 277 | 
            +
              const { dialogId } = useGetChatSearchParams();
         | 
| 278 | 
            +
             | 
| 279 | 
            +
              const setConversation = (message: string) => {
         | 
| 280 | 
            +
                return dispatch<any>({
         | 
| 281 | 
            +
                  type: 'chatModel/setConversation',
         | 
| 282 | 
            +
                  payload: {
         | 
| 283 | 
            +
                    // conversation_id: '',
         | 
| 284 | 
            +
                    dialog_id: dialogId,
         | 
| 285 | 
            +
                    name: message,
         | 
| 286 | 
            +
                    message: [
         | 
| 287 | 
            +
                      {
         | 
| 288 | 
            +
                        role: MessageType.Assistant,
         | 
| 289 | 
            +
                        content: message,
         | 
| 290 | 
            +
                      },
         | 
| 291 | 
            +
                    ],
         | 
| 292 | 
            +
                  },
         | 
| 293 | 
            +
                });
         | 
| 294 | 
            +
              };
         | 
| 295 | 
            +
             | 
| 296 | 
            +
              return { setConversation };
         | 
| 297 | 
            +
            };
         | 
| 298 | 
            +
             | 
| 299 | 
            +
            export const useFetchConversation = () => {
         | 
| 300 | 
            +
              const dispatch = useDispatch();
         | 
| 301 | 
            +
              const { conversationId } = useGetChatSearchParams();
         | 
| 302 | 
            +
              const conversation = useSelector(
         | 
| 303 | 
            +
                (state: any) => state.chatModel.currentConversation,
         | 
| 304 | 
            +
              );
         | 
| 305 | 
            +
             | 
| 306 | 
            +
              const fetchConversation = useCallback(() => {
         | 
| 307 | 
            +
                if (conversationId !== EmptyConversationId && conversationId !== '') {
         | 
| 308 | 
            +
                  dispatch({
         | 
| 309 | 
            +
                    type: 'chatModel/getConversation',
         | 
| 310 | 
            +
                    payload: {
         | 
| 311 | 
            +
                      conversation_id: conversationId,
         | 
| 312 | 
            +
                    },
         | 
| 313 | 
            +
                  });
         | 
| 314 | 
            +
                }
         | 
| 315 | 
            +
              }, [dispatch, conversationId]);
         | 
| 316 | 
            +
             | 
| 317 | 
            +
              useEffect(() => {
         | 
| 318 | 
            +
                fetchConversation();
         | 
| 319 | 
            +
              }, [fetchConversation]);
         | 
| 320 | 
            +
             | 
| 321 | 
            +
              return conversation;
         | 
| 322 | 
            +
            };
         | 
| 323 | 
            +
             | 
| 324 | 
            +
            export const useSendMessage = () => {
         | 
| 325 | 
            +
              const dispatch = useDispatch();
         | 
| 326 | 
            +
              const { setConversation } = useSetConversation();
         | 
| 327 | 
            +
              const { conversationId } = useGetChatSearchParams();
         | 
| 328 | 
            +
              const conversation = useSelector(
         | 
| 329 | 
            +
                (state: any) => state.chatModel.currentConversation,
         | 
| 330 | 
            +
              );
         | 
| 331 | 
            +
              const { handleClickConversation } = useClickConversationCard();
         | 
| 332 | 
            +
             | 
| 333 | 
            +
              const sendMessage = (message: string, id?: string) => {
         | 
| 334 | 
            +
                dispatch({
         | 
| 335 | 
            +
                  type: 'chatModel/completeConversation',
         | 
| 336 | 
            +
                  payload: {
         | 
| 337 | 
            +
                    conversation_id: id ?? conversationId,
         | 
| 338 | 
            +
                    messages: [
         | 
| 339 | 
            +
                      ...(conversation?.message ?? []).map((x: IMessage) => omit(x, 'id')),
         | 
| 340 | 
            +
                      {
         | 
| 341 | 
            +
                        role: MessageType.User,
         | 
| 342 | 
            +
                        content: message,
         | 
| 343 | 
            +
                      },
         | 
| 344 | 
            +
                    ],
         | 
| 345 | 
            +
                  },
         | 
| 346 | 
            +
                });
         | 
| 347 | 
            +
              };
         | 
| 348 | 
            +
             | 
| 349 | 
            +
              const handleSendMessage = async (message: string) => {
         | 
| 350 | 
            +
                if (conversationId !== EmptyConversationId) {
         | 
| 351 | 
            +
                  sendMessage(message);
         | 
| 352 | 
            +
                } else {
         | 
| 353 | 
            +
                  const data = await setConversation(message);
         | 
| 354 | 
            +
                  if (data.retcode === 0) {
         | 
| 355 | 
            +
                    const id = data.data.id;
         | 
| 356 | 
            +
                    handleClickConversation(id);
         | 
| 357 | 
            +
                    sendMessage(message, id);
         | 
| 358 | 
            +
                  }
         | 
| 359 | 
            +
                }
         | 
| 360 | 
            +
              };
         | 
| 361 | 
            +
             | 
| 362 | 
            +
              return { sendMessage: handleSendMessage };
         | 
| 363 | 
            +
            };
         | 
| 364 | 
            +
             | 
| 365 | 
            +
            //#endregion
         | 
    	
        web/src/pages/chat/index.less
    CHANGED
    
    | @@ -5,6 +5,10 @@ | |
| 5 | 
             
                width: 288px;
         | 
| 6 | 
             
                padding: 26px;
         | 
| 7 |  | 
|  | |
|  | |
|  | |
|  | |
| 8 | 
             
                .chatAppCard {
         | 
| 9 | 
             
                  :global(.ant-card-body) {
         | 
| 10 | 
             
                    padding: 10px;
         | 
| @@ -15,6 +19,12 @@ | |
| 15 | 
             
                    }
         | 
| 16 | 
             
                  }
         | 
| 17 | 
             
                }
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 18 | 
             
              }
         | 
| 19 | 
             
              .chatTitleWrapper {
         | 
| 20 | 
             
                width: 220px;
         | 
| @@ -29,6 +39,19 @@ | |
| 29 | 
             
                padding: 5px 10px;
         | 
| 30 | 
             
              }
         | 
| 31 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 32 | 
             
              .divider {
         | 
| 33 | 
             
                margin: 0;
         | 
| 34 | 
             
                height: 100%;
         | 
|  | |
| 5 | 
             
                width: 288px;
         | 
| 6 | 
             
                padding: 26px;
         | 
| 7 |  | 
| 8 | 
            +
                .chatAppContent {
         | 
| 9 | 
            +
                  overflow-y: auto;
         | 
| 10 | 
            +
                }
         | 
| 11 | 
            +
             | 
| 12 | 
             
                .chatAppCard {
         | 
| 13 | 
             
                  :global(.ant-card-body) {
         | 
| 14 | 
             
                    padding: 10px;
         | 
|  | |
| 19 | 
             
                    }
         | 
| 20 | 
             
                  }
         | 
| 21 | 
             
                }
         | 
| 22 | 
            +
                .chatAppCardSelected {
         | 
| 23 | 
            +
                  :global(.ant-card-body) {
         | 
| 24 | 
            +
                    background-color: @gray11;
         | 
| 25 | 
            +
                    border-radius: 8px;
         | 
| 26 | 
            +
                  }
         | 
| 27 | 
            +
                }
         | 
| 28 | 
             
              }
         | 
| 29 | 
             
              .chatTitleWrapper {
         | 
| 30 | 
             
                width: 220px;
         | 
|  | |
| 39 | 
             
                padding: 5px 10px;
         | 
| 40 | 
             
              }
         | 
| 41 |  | 
| 42 | 
            +
              .chatTitleCard {
         | 
| 43 | 
            +
                :global(.ant-card-body) {
         | 
| 44 | 
            +
                  padding: 8px;
         | 
| 45 | 
            +
                }
         | 
| 46 | 
            +
              }
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              .chatTitleCardSelected {
         | 
| 49 | 
            +
                :global(.ant-card-body) {
         | 
| 50 | 
            +
                  background-color: @gray11;
         | 
| 51 | 
            +
                  border-radius: 8px;
         | 
| 52 | 
            +
                }
         | 
| 53 | 
            +
              }
         | 
| 54 | 
            +
             | 
| 55 | 
             
              .divider {
         | 
| 56 | 
             
                margin: 0;
         | 
| 57 | 
             
                height: 100%;
         | 
    	
        web/src/pages/chat/index.tsx
    CHANGED
    
    | @@ -1,3 +1,5 @@ | |
|  | |
|  | |
| 1 | 
             
            import { DeleteOutlined, EditOutlined, FormOutlined } from '@ant-design/icons';
         | 
| 2 | 
             
            import {
         | 
| 3 | 
             
              Button,
         | 
| @@ -9,20 +11,39 @@ import { | |
| 9 | 
             
              Space,
         | 
| 10 | 
             
              Tag,
         | 
| 11 | 
             
            } from 'antd';
         | 
| 12 | 
            -
            import ChatContainer from './chat-container';
         | 
| 13 | 
            -
             | 
| 14 | 
            -
            import { ReactComponent as ChatAppCube } from '@/assets/svg/chat-app-cube.svg';
         | 
| 15 | 
            -
            import ModalManager from '@/components/modal-manager';
         | 
| 16 | 
             
            import classNames from 'classnames';
         | 
|  | |
| 17 | 
             
            import ChatConfigurationModal from './chat-configuration-modal';
         | 
| 18 | 
            -
            import  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 19 |  | 
| 20 | 
            -
            import { useState } from 'react';
         | 
| 21 | 
             
            import styles from './index.less';
         | 
| 22 |  | 
| 23 | 
             
            const Chat = () => {
         | 
| 24 | 
            -
              const dialogList =  | 
| 25 | 
             
              const [activated, setActivated] = useState<string>('');
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 26 |  | 
| 27 | 
             
              const handleAppCardEnter = (id: string) => () => {
         | 
| 28 | 
             
                setActivated(id);
         | 
| @@ -32,72 +53,84 @@ const Chat = () => { | |
| 32 | 
             
                setActivated('');
         | 
| 33 | 
             
              };
         | 
| 34 |  | 
| 35 | 
            -
              const  | 
| 36 | 
            -
                {
         | 
| 37 | 
            -
                   | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
                 | 
| 48 | 
            -
               | 
|  | |
|  | |
|  | |
|  | |
| 49 |  | 
| 50 | 
            -
              const  | 
| 51 | 
             
                {
         | 
| 52 | 
             
                  key: '1',
         | 
|  | |
| 53 | 
             
                  label: (
         | 
| 54 | 
             
                    <Space>
         | 
| 55 | 
            -
                      <EditOutlined />
         | 
| 56 | 
            -
                      Edit
         | 
| 57 | 
            -
                    </Space>
         | 
| 58 | 
            -
                  ),
         | 
| 59 | 
            -
                },
         | 
| 60 | 
            -
                { type: 'divider' },
         | 
| 61 | 
            -
                {
         | 
| 62 | 
            -
                  key: '2',
         | 
| 63 | 
            -
                  label: (
         | 
| 64 | 
            -
                    <Space>
         | 
| 65 | 
            -
                      <DeleteOutlined />
         | 
| 66 | 
            -
                      Delete chat
         | 
| 67 | 
             
                    </Space>
         | 
| 68 | 
             
                  ),
         | 
| 69 | 
             
                },
         | 
| 70 | 
             
              ];
         | 
| 71 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 72 | 
             
              return (
         | 
| 73 | 
             
                <Flex className={styles.chatWrapper}>
         | 
| 74 | 
             
                  <Flex className={styles.chatAppWrapper}>
         | 
| 75 | 
             
                    <Flex flex={1} vertical>
         | 
| 76 | 
            -
                      < | 
| 77 | 
            -
                         | 
| 78 | 
            -
             | 
| 79 | 
            -
                            <>
         | 
| 80 | 
            -
                              <Button type="primary" onClick={() => showModal()}>
         | 
| 81 | 
            -
                                Create an Assistant
         | 
| 82 | 
            -
                              </Button>
         | 
| 83 | 
            -
                              <ChatConfigurationModal
         | 
| 84 | 
            -
                                visible={visible}
         | 
| 85 | 
            -
                                showModal={showModal}
         | 
| 86 | 
            -
                                hideModal={hideModal}
         | 
| 87 | 
            -
                              ></ChatConfigurationModal>
         | 
| 88 | 
            -
                            </>
         | 
| 89 | 
            -
                          );
         | 
| 90 | 
            -
                        }}
         | 
| 91 | 
            -
                      </ModalManager>
         | 
| 92 | 
            -
             | 
| 93 | 
             
                      <Divider></Divider>
         | 
| 94 | 
            -
                      < | 
| 95 | 
             
                        {dialogList.map((x) => (
         | 
| 96 | 
             
                          <Card
         | 
| 97 | 
             
                            key={x.id}
         | 
| 98 | 
            -
                             | 
|  | |
|  | |
|  | |
| 99 | 
             
                            onMouseEnter={handleAppCardEnter(x.id)}
         | 
| 100 | 
             
                            onMouseLeave={handleAppCardLeave}
         | 
|  | |
| 101 | 
             
                          >
         | 
| 102 | 
             
                            <Flex justify="space-between" align="center">
         | 
| 103 | 
             
                              <Space>
         | 
| @@ -109,7 +142,7 @@ const Chat = () => { | |
| 109 | 
             
                              </Space>
         | 
| 110 | 
             
                              {activated === x.id && (
         | 
| 111 | 
             
                                <section>
         | 
| 112 | 
            -
                                  <Dropdown menu={{ items:  | 
| 113 | 
             
                                    <ChatAppCube className={styles.cubeIcon}></ChatAppCube>
         | 
| 114 | 
             
                                  </Dropdown>
         | 
| 115 | 
             
                                </section>
         | 
| @@ -117,7 +150,7 @@ const Chat = () => { | |
| 117 | 
             
                            </Flex>
         | 
| 118 | 
             
                          </Card>
         | 
| 119 | 
             
                        ))}
         | 
| 120 | 
            -
                      </ | 
| 121 | 
             
                    </Flex>
         | 
| 122 | 
             
                  </Flex>
         | 
| 123 | 
             
                  <Divider type={'vertical'} className={styles.divider}></Divider>
         | 
| @@ -137,11 +170,30 @@ const Chat = () => { | |
| 137 | 
             
                        </Dropdown>
         | 
| 138 | 
             
                      </Flex>
         | 
| 139 | 
             
                      <Divider></Divider>
         | 
| 140 | 
            -
                      < | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 141 | 
             
                    </Flex>
         | 
| 142 | 
             
                  </Flex>
         | 
| 143 | 
             
                  <Divider type={'vertical'} className={styles.divider}></Divider>
         | 
| 144 | 
             
                  <ChatContainer></ChatContainer>
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 145 | 
             
                </Flex>
         | 
| 146 | 
             
              );
         | 
| 147 | 
             
            };
         | 
|  | |
| 1 | 
            +
            import { ReactComponent as ChatAppCube } from '@/assets/svg/chat-app-cube.svg';
         | 
| 2 | 
            +
            import { useSetModalState } from '@/hooks/commonHooks';
         | 
| 3 | 
             
            import { DeleteOutlined, EditOutlined, FormOutlined } from '@ant-design/icons';
         | 
| 4 | 
             
            import {
         | 
| 5 | 
             
              Button,
         | 
|  | |
| 11 | 
             
              Space,
         | 
| 12 | 
             
              Tag,
         | 
| 13 | 
             
            } from 'antd';
         | 
|  | |
|  | |
|  | |
|  | |
| 14 | 
             
            import classNames from 'classnames';
         | 
| 15 | 
            +
            import { useCallback, useState } from 'react';
         | 
| 16 | 
             
            import ChatConfigurationModal from './chat-configuration-modal';
         | 
| 17 | 
            +
            import ChatContainer from './chat-container';
         | 
| 18 | 
            +
            import {
         | 
| 19 | 
            +
              useClickConversationCard,
         | 
| 20 | 
            +
              useClickDialogCard,
         | 
| 21 | 
            +
              useCreateTemporaryConversation,
         | 
| 22 | 
            +
              useFetchConversationList,
         | 
| 23 | 
            +
              useFetchDialog,
         | 
| 24 | 
            +
              useGetChatSearchParams,
         | 
| 25 | 
            +
              useRemoveDialog,
         | 
| 26 | 
            +
              useSelectFirstDialogOnMount,
         | 
| 27 | 
            +
              useSetCurrentDialog,
         | 
| 28 | 
            +
            } from './hooks';
         | 
| 29 |  | 
|  | |
| 30 | 
             
            import styles from './index.less';
         | 
| 31 |  | 
| 32 | 
             
            const Chat = () => {
         | 
| 33 | 
            +
              const dialogList = useSelectFirstDialogOnMount();
         | 
| 34 | 
             
              const [activated, setActivated] = useState<string>('');
         | 
| 35 | 
            +
              const { visible, hideModal, showModal } = useSetModalState();
         | 
| 36 | 
            +
              const { setCurrentDialog, currentDialog } = useSetCurrentDialog();
         | 
| 37 | 
            +
              const { onRemoveDialog } = useRemoveDialog();
         | 
| 38 | 
            +
              const { handleClickDialog } = useClickDialogCard();
         | 
| 39 | 
            +
              const { handleClickConversation } = useClickConversationCard();
         | 
| 40 | 
            +
              const { dialogId, conversationId } = useGetChatSearchParams();
         | 
| 41 | 
            +
              const list = useFetchConversationList(dialogId);
         | 
| 42 | 
            +
              const { createTemporaryConversation } = useCreateTemporaryConversation();
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              const selectedDialog = useFetchDialog(dialogId, true);
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              const prologue = selectedDialog?.prompt_config?.prologue || '';
         | 
| 47 |  | 
| 48 | 
             
              const handleAppCardEnter = (id: string) => () => {
         | 
| 49 | 
             
                setActivated(id);
         | 
|  | |
| 53 | 
             
                setActivated('');
         | 
| 54 | 
             
              };
         | 
| 55 |  | 
| 56 | 
            +
              const handleShowChatConfigurationModal = (dialogId?: string) => () => {
         | 
| 57 | 
            +
                if (dialogId) {
         | 
| 58 | 
            +
                  setCurrentDialog(dialogId);
         | 
| 59 | 
            +
                }
         | 
| 60 | 
            +
                showModal();
         | 
| 61 | 
            +
              };
         | 
| 62 | 
            +
             | 
| 63 | 
            +
              const handleDialogCardClick = (dialogId: string) => () => {
         | 
| 64 | 
            +
                handleClickDialog(dialogId);
         | 
| 65 | 
            +
              };
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              const handleConversationCardClick = (dialogId: string) => () => {
         | 
| 68 | 
            +
                handleClickConversation(dialogId);
         | 
| 69 | 
            +
              };
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              const handleCreateTemporaryConversation = useCallback(() => {
         | 
| 72 | 
            +
                createTemporaryConversation(prologue);
         | 
| 73 | 
            +
              }, [createTemporaryConversation, prologue]);
         | 
| 74 |  | 
| 75 | 
            +
              const items: MenuProps['items'] = [
         | 
| 76 | 
             
                {
         | 
| 77 | 
             
                  key: '1',
         | 
| 78 | 
            +
                  onClick: handleCreateTemporaryConversation,
         | 
| 79 | 
             
                  label: (
         | 
| 80 | 
             
                    <Space>
         | 
| 81 | 
            +
                      <EditOutlined /> New chat
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 82 | 
             
                    </Space>
         | 
| 83 | 
             
                  ),
         | 
| 84 | 
             
                },
         | 
| 85 | 
             
              ];
         | 
| 86 |  | 
| 87 | 
            +
              const buildAppItems = (dialogId: string) => {
         | 
| 88 | 
            +
                const appItems: MenuProps['items'] = [
         | 
| 89 | 
            +
                  {
         | 
| 90 | 
            +
                    key: '1',
         | 
| 91 | 
            +
                    onClick: handleShowChatConfigurationModal(dialogId),
         | 
| 92 | 
            +
                    label: (
         | 
| 93 | 
            +
                      <Space>
         | 
| 94 | 
            +
                        <EditOutlined />
         | 
| 95 | 
            +
                        Edit
         | 
| 96 | 
            +
                      </Space>
         | 
| 97 | 
            +
                    ),
         | 
| 98 | 
            +
                  },
         | 
| 99 | 
            +
                  { type: 'divider' },
         | 
| 100 | 
            +
                  {
         | 
| 101 | 
            +
                    key: '2',
         | 
| 102 | 
            +
                    onClick: () => onRemoveDialog([dialogId]),
         | 
| 103 | 
            +
                    label: (
         | 
| 104 | 
            +
                      <Space>
         | 
| 105 | 
            +
                        <DeleteOutlined />
         | 
| 106 | 
            +
                        Delete chat
         | 
| 107 | 
            +
                      </Space>
         | 
| 108 | 
            +
                    ),
         | 
| 109 | 
            +
                  },
         | 
| 110 | 
            +
                ];
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                return appItems;
         | 
| 113 | 
            +
              };
         | 
| 114 | 
            +
             | 
| 115 | 
             
              return (
         | 
| 116 | 
             
                <Flex className={styles.chatWrapper}>
         | 
| 117 | 
             
                  <Flex className={styles.chatAppWrapper}>
         | 
| 118 | 
             
                    <Flex flex={1} vertical>
         | 
| 119 | 
            +
                      <Button type="primary" onClick={handleShowChatConfigurationModal()}>
         | 
| 120 | 
            +
                        Create an Assistant
         | 
| 121 | 
            +
                      </Button>
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 122 | 
             
                      <Divider></Divider>
         | 
| 123 | 
            +
                      <Flex className={styles.chatAppContent} vertical gap={10}>
         | 
| 124 | 
             
                        {dialogList.map((x) => (
         | 
| 125 | 
             
                          <Card
         | 
| 126 | 
             
                            key={x.id}
         | 
| 127 | 
            +
                            hoverable
         | 
| 128 | 
            +
                            className={classNames(styles.chatAppCard, {
         | 
| 129 | 
            +
                              [styles.chatAppCardSelected]: dialogId === x.id,
         | 
| 130 | 
            +
                            })}
         | 
| 131 | 
             
                            onMouseEnter={handleAppCardEnter(x.id)}
         | 
| 132 | 
             
                            onMouseLeave={handleAppCardLeave}
         | 
| 133 | 
            +
                            onClick={handleDialogCardClick(x.id)}
         | 
| 134 | 
             
                          >
         | 
| 135 | 
             
                            <Flex justify="space-between" align="center">
         | 
| 136 | 
             
                              <Space>
         | 
|  | |
| 142 | 
             
                              </Space>
         | 
| 143 | 
             
                              {activated === x.id && (
         | 
| 144 | 
             
                                <section>
         | 
| 145 | 
            +
                                  <Dropdown menu={{ items: buildAppItems(x.id) }}>
         | 
| 146 | 
             
                                    <ChatAppCube className={styles.cubeIcon}></ChatAppCube>
         | 
| 147 | 
             
                                  </Dropdown>
         | 
| 148 | 
             
                                </section>
         | 
|  | |
| 150 | 
             
                            </Flex>
         | 
| 151 | 
             
                          </Card>
         | 
| 152 | 
             
                        ))}
         | 
| 153 | 
            +
                      </Flex>
         | 
| 154 | 
             
                    </Flex>
         | 
| 155 | 
             
                  </Flex>
         | 
| 156 | 
             
                  <Divider type={'vertical'} className={styles.divider}></Divider>
         | 
|  | |
| 170 | 
             
                        </Dropdown>
         | 
| 171 | 
             
                      </Flex>
         | 
| 172 | 
             
                      <Divider></Divider>
         | 
| 173 | 
            +
                      <Flex vertical gap={10} className={styles.chatTitleContent}>
         | 
| 174 | 
            +
                        {list.map((x) => (
         | 
| 175 | 
            +
                          <Card
         | 
| 176 | 
            +
                            key={x.id}
         | 
| 177 | 
            +
                            hoverable
         | 
| 178 | 
            +
                            onClick={handleConversationCardClick(x.id)}
         | 
| 179 | 
            +
                            className={classNames(styles.chatTitleCard, {
         | 
| 180 | 
            +
                              [styles.chatTitleCardSelected]: x.id === conversationId,
         | 
| 181 | 
            +
                            })}
         | 
| 182 | 
            +
                          >
         | 
| 183 | 
            +
                            <div>{x.name}</div>
         | 
| 184 | 
            +
                          </Card>
         | 
| 185 | 
            +
                        ))}
         | 
| 186 | 
            +
                      </Flex>
         | 
| 187 | 
             
                    </Flex>
         | 
| 188 | 
             
                  </Flex>
         | 
| 189 | 
             
                  <Divider type={'vertical'} className={styles.divider}></Divider>
         | 
| 190 | 
             
                  <ChatContainer></ChatContainer>
         | 
| 191 | 
            +
                  <ChatConfigurationModal
         | 
| 192 | 
            +
                    visible={visible}
         | 
| 193 | 
            +
                    showModal={showModal}
         | 
| 194 | 
            +
                    hideModal={hideModal}
         | 
| 195 | 
            +
                    id={currentDialog.id}
         | 
| 196 | 
            +
                  ></ChatConfigurationModal>
         | 
| 197 | 
             
                </Flex>
         | 
| 198 | 
             
              );
         | 
| 199 | 
             
            };
         | 
    	
        web/src/pages/chat/{chat-configuration-modal/interface.ts → interface.ts}
    RENAMED
    
    | @@ -1,3 +1,4 @@ | |
|  | |
| 1 | 
             
            import { FormInstance } from 'antd';
         | 
| 2 |  | 
| 3 | 
             
            export interface ISegmentedContentProps {
         | 
| @@ -12,3 +13,19 @@ export interface IVariable { | |
| 12 | 
             
              presence_penalty: number;
         | 
| 13 | 
             
              max_tokens: number;
         | 
| 14 | 
             
            }
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import { IConversation, Message } from '@/interfaces/database/chat';
         | 
| 2 | 
             
            import { FormInstance } from 'antd';
         | 
| 3 |  | 
| 4 | 
             
            export interface ISegmentedContentProps {
         | 
|  | |
| 13 | 
             
              presence_penalty: number;
         | 
| 14 | 
             
              max_tokens: number;
         | 
| 15 | 
             
            }
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            export interface VariableTableDataType {
         | 
| 18 | 
            +
              key: string;
         | 
| 19 | 
            +
              variable: string;
         | 
| 20 | 
            +
              optional: boolean;
         | 
| 21 | 
            +
            }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            export type IPromptConfigParameters = Omit<VariableTableDataType, 'variable'>;
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            export interface IMessage extends Message {
         | 
| 26 | 
            +
              id: string;
         | 
| 27 | 
            +
            }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            export interface IClientConversation extends IConversation {
         | 
| 30 | 
            +
              message: IMessage[];
         | 
| 31 | 
            +
            }
         | 
    	
        web/src/pages/chat/model.ts
    CHANGED
    
    | @@ -1,11 +1,16 @@ | |
| 1 | 
            -
            import { IDialog } from '@/interfaces/database/chat';
         | 
| 2 | 
             
            import chatService from '@/services/chatService';
         | 
| 3 | 
             
            import { message } from 'antd';
         | 
| 4 | 
             
            import { DvaModel } from 'umi';
         | 
|  | |
|  | |
| 5 |  | 
| 6 | 
             
            export interface ChatModelState {
         | 
| 7 | 
             
              name: string;
         | 
| 8 | 
             
              dialogList: IDialog[];
         | 
|  | |
|  | |
|  | |
| 9 | 
             
            }
         | 
| 10 |  | 
| 11 | 
             
            const model: DvaModel<ChatModelState> = {
         | 
| @@ -13,6 +18,9 @@ const model: DvaModel<ChatModelState> = { | |
| 13 | 
             
              state: {
         | 
| 14 | 
             
                name: 'kate',
         | 
| 15 | 
             
                dialogList: [],
         | 
|  | |
|  | |
|  | |
| 16 | 
             
              },
         | 
| 17 | 
             
              reducers: {
         | 
| 18 | 
             
                save(state, action) {
         | 
| @@ -27,11 +35,50 @@ const model: DvaModel<ChatModelState> = { | |
| 27 | 
             
                    dialogList: payload,
         | 
| 28 | 
             
                  };
         | 
| 29 | 
             
                },
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 30 | 
             
              },
         | 
| 31 |  | 
| 32 | 
             
              effects: {
         | 
| 33 | 
             
                *getDialog({ payload }, { call, put }) {
         | 
| 34 | 
             
                  const { data } = yield call(chatService.getDialog, payload);
         | 
|  | |
|  | |
|  | |
| 35 | 
             
                },
         | 
| 36 | 
             
                *setDialog({ payload }, { call, put }) {
         | 
| 37 | 
             
                  const { data } = yield call(chatService.setDialog, payload);
         | 
| @@ -39,6 +86,15 @@ const model: DvaModel<ChatModelState> = { | |
| 39 | 
             
                    yield put({ type: 'listDialog' });
         | 
| 40 | 
             
                    message.success('Created successfully !');
         | 
| 41 | 
             
                  }
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 42 | 
             
                },
         | 
| 43 | 
             
                *listDialog({ payload }, { call, put }) {
         | 
| 44 | 
             
                  const { data } = yield call(chatService.listDialog, payload);
         | 
| @@ -46,15 +102,40 @@ const model: DvaModel<ChatModelState> = { | |
| 46 | 
             
                },
         | 
| 47 | 
             
                *listConversation({ payload }, { call, put }) {
         | 
| 48 | 
             
                  const { data } = yield call(chatService.listConversation, payload);
         | 
|  | |
|  | |
|  | |
|  | |
| 49 | 
             
                },
         | 
| 50 | 
             
                *getConversation({ payload }, { call, put }) {
         | 
| 51 | 
             
                  const { data } = yield call(chatService.getConversation, payload);
         | 
|  | |
|  | |
|  | |
|  | |
| 52 | 
             
                },
         | 
| 53 | 
             
                *setConversation({ payload }, { call, put }) {
         | 
| 54 | 
             
                  const { data } = yield call(chatService.setConversation, payload);
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 55 | 
             
                },
         | 
| 56 | 
             
                *completeConversation({ payload }, { call, put }) {
         | 
| 57 | 
             
                  const { data } = yield call(chatService.completeConversation, payload);
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 58 | 
             
                },
         | 
| 59 | 
             
              },
         | 
| 60 | 
             
            };
         | 
|  | |
| 1 | 
            +
            import { IConversation, IDialog, Message } from '@/interfaces/database/chat';
         | 
| 2 | 
             
            import chatService from '@/services/chatService';
         | 
| 3 | 
             
            import { message } from 'antd';
         | 
| 4 | 
             
            import { DvaModel } from 'umi';
         | 
| 5 | 
            +
            import { v4 as uuid } from 'uuid';
         | 
| 6 | 
            +
            import { IClientConversation, IMessage } from './interface';
         | 
| 7 |  | 
| 8 | 
             
            export interface ChatModelState {
         | 
| 9 | 
             
              name: string;
         | 
| 10 | 
             
              dialogList: IDialog[];
         | 
| 11 | 
            +
              currentDialog: IDialog;
         | 
| 12 | 
            +
              conversationList: IConversation[];
         | 
| 13 | 
            +
              currentConversation: IClientConversation;
         | 
| 14 | 
             
            }
         | 
| 15 |  | 
| 16 | 
             
            const model: DvaModel<ChatModelState> = {
         | 
|  | |
| 18 | 
             
              state: {
         | 
| 19 | 
             
                name: 'kate',
         | 
| 20 | 
             
                dialogList: [],
         | 
| 21 | 
            +
                currentDialog: <IDialog>{},
         | 
| 22 | 
            +
                conversationList: [],
         | 
| 23 | 
            +
                currentConversation: {} as IClientConversation,
         | 
| 24 | 
             
              },
         | 
| 25 | 
             
              reducers: {
         | 
| 26 | 
             
                save(state, action) {
         | 
|  | |
| 35 | 
             
                    dialogList: payload,
         | 
| 36 | 
             
                  };
         | 
| 37 | 
             
                },
         | 
| 38 | 
            +
                setCurrentDialog(state, { payload }) {
         | 
| 39 | 
            +
                  return {
         | 
| 40 | 
            +
                    ...state,
         | 
| 41 | 
            +
                    currentDialog: payload,
         | 
| 42 | 
            +
                  };
         | 
| 43 | 
            +
                },
         | 
| 44 | 
            +
                setConversationList(state, { payload }) {
         | 
| 45 | 
            +
                  return {
         | 
| 46 | 
            +
                    ...state,
         | 
| 47 | 
            +
                    conversationList: payload,
         | 
| 48 | 
            +
                  };
         | 
| 49 | 
            +
                },
         | 
| 50 | 
            +
                setCurrentConversation(state, { payload }) {
         | 
| 51 | 
            +
                  const messageList = payload?.message.map((x: Message | IMessage) => ({
         | 
| 52 | 
            +
                    ...x,
         | 
| 53 | 
            +
                    id: 'id' in x ? x.id : uuid(),
         | 
| 54 | 
            +
                  }));
         | 
| 55 | 
            +
                  return {
         | 
| 56 | 
            +
                    ...state,
         | 
| 57 | 
            +
                    currentConversation: { ...payload, message: messageList },
         | 
| 58 | 
            +
                  };
         | 
| 59 | 
            +
                },
         | 
| 60 | 
            +
                addEmptyConversationToList(state, {}) {
         | 
| 61 | 
            +
                  const list = [...state.conversationList];
         | 
| 62 | 
            +
                  // if (list.every((x) => x.id !== 'empty')) {
         | 
| 63 | 
            +
                  //   list.push({
         | 
| 64 | 
            +
                  //     id: 'empty',
         | 
| 65 | 
            +
                  //     name: 'New conversation',
         | 
| 66 | 
            +
                  //     message: [],
         | 
| 67 | 
            +
                  //   });
         | 
| 68 | 
            +
                  // }
         | 
| 69 | 
            +
                  return {
         | 
| 70 | 
            +
                    ...state,
         | 
| 71 | 
            +
                    conversationList: list,
         | 
| 72 | 
            +
                  };
         | 
| 73 | 
            +
                },
         | 
| 74 | 
             
              },
         | 
| 75 |  | 
| 76 | 
             
              effects: {
         | 
| 77 | 
             
                *getDialog({ payload }, { call, put }) {
         | 
| 78 | 
             
                  const { data } = yield call(chatService.getDialog, payload);
         | 
| 79 | 
            +
                  if (data.retcode === 0) {
         | 
| 80 | 
            +
                    yield put({ type: 'setCurrentDialog', payload: data.data });
         | 
| 81 | 
            +
                  }
         | 
| 82 | 
             
                },
         | 
| 83 | 
             
                *setDialog({ payload }, { call, put }) {
         | 
| 84 | 
             
                  const { data } = yield call(chatService.setDialog, payload);
         | 
|  | |
| 86 | 
             
                    yield put({ type: 'listDialog' });
         | 
| 87 | 
             
                    message.success('Created successfully !');
         | 
| 88 | 
             
                  }
         | 
| 89 | 
            +
                  return data.retcode;
         | 
| 90 | 
            +
                },
         | 
| 91 | 
            +
                *removeDialog({ payload }, { call, put }) {
         | 
| 92 | 
            +
                  const { data } = yield call(chatService.removeDialog, payload);
         | 
| 93 | 
            +
                  if (data.retcode === 0) {
         | 
| 94 | 
            +
                    yield put({ type: 'listDialog' });
         | 
| 95 | 
            +
                    message.success('Deleted successfully !');
         | 
| 96 | 
            +
                  }
         | 
| 97 | 
            +
                  return data.retcode;
         | 
| 98 | 
             
                },
         | 
| 99 | 
             
                *listDialog({ payload }, { call, put }) {
         | 
| 100 | 
             
                  const { data } = yield call(chatService.listDialog, payload);
         | 
|  | |
| 102 | 
             
                },
         | 
| 103 | 
             
                *listConversation({ payload }, { call, put }) {
         | 
| 104 | 
             
                  const { data } = yield call(chatService.listConversation, payload);
         | 
| 105 | 
            +
                  if (data.retcode === 0) {
         | 
| 106 | 
            +
                    yield put({ type: 'setConversationList', payload: data.data });
         | 
| 107 | 
            +
                  }
         | 
| 108 | 
            +
                  return data.retcode;
         | 
| 109 | 
             
                },
         | 
| 110 | 
             
                *getConversation({ payload }, { call, put }) {
         | 
| 111 | 
             
                  const { data } = yield call(chatService.getConversation, payload);
         | 
| 112 | 
            +
                  if (data.retcode === 0) {
         | 
| 113 | 
            +
                    yield put({ type: 'setCurrentConversation', payload: data.data });
         | 
| 114 | 
            +
                  }
         | 
| 115 | 
            +
                  return data.retcode;
         | 
| 116 | 
             
                },
         | 
| 117 | 
             
                *setConversation({ payload }, { call, put }) {
         | 
| 118 | 
             
                  const { data } = yield call(chatService.setConversation, payload);
         | 
| 119 | 
            +
                  if (data.retcode === 0) {
         | 
| 120 | 
            +
                    yield put({
         | 
| 121 | 
            +
                      type: 'listConversation',
         | 
| 122 | 
            +
                      payload: {
         | 
| 123 | 
            +
                        dialog_id: data.data.dialog_id,
         | 
| 124 | 
            +
                      },
         | 
| 125 | 
            +
                    });
         | 
| 126 | 
            +
                  }
         | 
| 127 | 
            +
                  return data;
         | 
| 128 | 
             
                },
         | 
| 129 | 
             
                *completeConversation({ payload }, { call, put }) {
         | 
| 130 | 
             
                  const { data } = yield call(chatService.completeConversation, payload);
         | 
| 131 | 
            +
                  if (data.retcode === 0) {
         | 
| 132 | 
            +
                    yield put({
         | 
| 133 | 
            +
                      type: 'getConversation',
         | 
| 134 | 
            +
                      payload: {
         | 
| 135 | 
            +
                        conversation_id: payload.conversation_id,
         | 
| 136 | 
            +
                      },
         | 
| 137 | 
            +
                    });
         | 
| 138 | 
            +
                  }
         | 
| 139 | 
             
                },
         | 
| 140 | 
             
              },
         | 
| 141 | 
             
            };
         | 
    	
        web/src/pages/chat/utils.ts
    ADDED
    
    | @@ -0,0 +1,12 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import { variableEnabledFieldMap } from './constants';
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            export const excludeUnEnabledVariables = (values: any) => {
         | 
| 4 | 
            +
              const unEnabledFields: Array<keyof typeof variableEnabledFieldMap> =
         | 
| 5 | 
            +
                Object.keys(variableEnabledFieldMap).filter((key) => !values[key]) as Array<
         | 
| 6 | 
            +
                  keyof typeof variableEnabledFieldMap
         | 
| 7 | 
            +
                >;
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              return unEnabledFields.map(
         | 
| 10 | 
            +
                (key) => `llm_setting.${variableEnabledFieldMap[key]}`,
         | 
| 11 | 
            +
              );
         | 
| 12 | 
            +
            };
         | 
    	
        web/src/pages/knowledge/model.ts
    CHANGED
    
    | @@ -31,7 +31,7 @@ const model: DvaModel<KnowledgeModelState> = { | |
| 31 | 
             
                },
         | 
| 32 | 
             
                *getList({ payload = {} }, { call, put }) {
         | 
| 33 | 
             
                  const { data } = yield call(kbService.getList, payload);
         | 
| 34 | 
            -
                  const { retcode, data: res | 
| 35 |  | 
| 36 | 
             
                  if (retcode === 0) {
         | 
| 37 | 
             
                    yield put({
         | 
|  | |
| 31 | 
             
                },
         | 
| 32 | 
             
                *getList({ payload = {} }, { call, put }) {
         | 
| 33 | 
             
                  const { data } = yield call(kbService.getList, payload);
         | 
| 34 | 
            +
                  const { retcode, data: res } = data;
         | 
| 35 |  | 
| 36 | 
             
                  if (retcode === 0) {
         | 
| 37 | 
             
                    yield put({
         | 
    	
        web/src/services/chatService.ts
    CHANGED
    
    | @@ -6,6 +6,7 @@ const { | |
| 6 | 
             
              getDialog,
         | 
| 7 | 
             
              setDialog,
         | 
| 8 | 
             
              listDialog,
         | 
|  | |
| 9 | 
             
              getConversation,
         | 
| 10 | 
             
              setConversation,
         | 
| 11 | 
             
              completeConversation,
         | 
| @@ -21,6 +22,10 @@ const methods = { | |
| 21 | 
             
                url: setDialog,
         | 
| 22 | 
             
                method: 'post',
         | 
| 23 | 
             
              },
         | 
|  | |
|  | |
|  | |
|  | |
| 24 | 
             
              listDialog: {
         | 
| 25 | 
             
                url: listDialog,
         | 
| 26 | 
             
                method: 'get',
         | 
|  | |
| 6 | 
             
              getDialog,
         | 
| 7 | 
             
              setDialog,
         | 
| 8 | 
             
              listDialog,
         | 
| 9 | 
            +
              removeDialog,
         | 
| 10 | 
             
              getConversation,
         | 
| 11 | 
             
              setConversation,
         | 
| 12 | 
             
              completeConversation,
         | 
|  | |
| 22 | 
             
                url: setDialog,
         | 
| 23 | 
             
                method: 'post',
         | 
| 24 | 
             
              },
         | 
| 25 | 
            +
              removeDialog: {
         | 
| 26 | 
            +
                url: removeDialog,
         | 
| 27 | 
            +
                method: 'post',
         | 
| 28 | 
            +
              },
         | 
| 29 | 
             
              listDialog: {
         | 
| 30 | 
             
                url: listDialog,
         | 
| 31 | 
             
                method: 'get',
         | 
    	
        web/src/utils/api.ts
    CHANGED
    
    | @@ -45,6 +45,7 @@ export default { | |
| 45 |  | 
| 46 | 
             
              setDialog: `${api_host}/dialog/set`,
         | 
| 47 | 
             
              getDialog: `${api_host}/dialog/get`,
         | 
|  | |
| 48 | 
             
              listDialog: `${api_host}/dialog/list`,
         | 
| 49 |  | 
| 50 | 
             
              setConversation: `${api_host}/conversation/set`,
         | 
|  | |
| 45 |  | 
| 46 | 
             
              setDialog: `${api_host}/dialog/set`,
         | 
| 47 | 
             
              getDialog: `${api_host}/dialog/get`,
         | 
| 48 | 
            +
              removeDialog: `${api_host}/dialog/rm`,
         | 
| 49 | 
             
              listDialog: `${api_host}/dialog/list`,
         | 
| 50 |  | 
| 51 | 
             
              setConversation: `${api_host}/conversation/set`,
         |