diff --git a/web/src/assets/svg/chunk-method/law-01.svg b/web/src/assets/svg/chunk-method/law-01.svg index 5b87a77de..9ce68793f 100644 --- a/web/src/assets/svg/chunk-method/law-01.svg +++ b/web/src/assets/svg/chunk-method/law-01.svg @@ -1,80 +1,96 @@ - + - + fill="url(#paint0_radial_912_25648)" /> - - - - - - - - - - + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - + - + - - + - - + + - - + + - - + + - + \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/law-02.svg b/web/src/assets/svg/chunk-method/law-02.svg index 23a7f0f7b..5aedb4569 100644 --- a/web/src/assets/svg/chunk-method/law-02.svg +++ b/web/src/assets/svg/chunk-method/law-02.svg @@ -1,80 +1,80 @@ - + - + fill="url(#paint0_radial_912_25651)" /> - - - - - - - - - - + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - + - + - - + - - + + - - + + - - + + - + \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/law-03.svg b/web/src/assets/svg/chunk-method/law-03.svg deleted file mode 100644 index 707a7a8a7..000000000 --- a/web/src/assets/svg/chunk-method/law-03.svg +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/law-04.svg b/web/src/assets/svg/chunk-method/law-04.svg deleted file mode 100644 index 9a40f7c8b..000000000 --- a/web/src/assets/svg/chunk-method/law-04.svg +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/manual-01.svg b/web/src/assets/svg/chunk-method/manual-01.svg index 37f72baa5..52a5992ef 100644 --- a/web/src/assets/svg/chunk-method/manual-01.svg +++ b/web/src/assets/svg/chunk-method/manual-01.svg @@ -1,15 +1,15 @@ - + - + fill="url(#paint0_radial_912_26163)" /> - - - + + + @@ -29,7 +29,7 @@ - + @@ -50,30 +50,30 @@ - + - + - - + - + - + - + - + \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/manual-02.svg b/web/src/assets/svg/chunk-method/manual-02.svg index ed0fd7995..632ca8768 100644 --- a/web/src/assets/svg/chunk-method/manual-02.svg +++ b/web/src/assets/svg/chunk-method/manual-02.svg @@ -1,15 +1,15 @@ - + - + fill="url(#paint0_radial_912_26166)" /> - - - + + + @@ -29,7 +29,7 @@ - + @@ -50,30 +50,30 @@ - + - + - - + - + - + - + - + \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/manual-03.svg b/web/src/assets/svg/chunk-method/manual-03.svg index 11754e506..420bcde55 100644 --- a/web/src/assets/svg/chunk-method/manual-03.svg +++ b/web/src/assets/svg/chunk-method/manual-03.svg @@ -1,15 +1,15 @@ - + - + fill="url(#paint0_radial_912_26170)" /> - - - + + + @@ -29,7 +29,7 @@ - + @@ -50,31 +50,30 @@ - + - + - - + - + - + - + - + \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/manual-04.svg b/web/src/assets/svg/chunk-method/manual-04.svg index a5ead4e90..0dc410e10 100644 --- a/web/src/assets/svg/chunk-method/manual-04.svg +++ b/web/src/assets/svg/chunk-method/manual-04.svg @@ -1,15 +1,15 @@ - + - + fill="url(#paint0_radial_912_26173)" /> - - - + + + @@ -29,7 +29,7 @@ - + @@ -50,30 +50,30 @@ - + - + - - + - + - + - + - + \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/one-01.svg b/web/src/assets/svg/chunk-method/one-01.svg new file mode 100644 index 000000000..37f72baa5 --- /dev/null +++ b/web/src/assets/svg/chunk-method/one-01.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/one-02.svg b/web/src/assets/svg/chunk-method/one-02.svg new file mode 100644 index 000000000..ed0fd7995 --- /dev/null +++ b/web/src/assets/svg/chunk-method/one-02.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/one-03.svg b/web/src/assets/svg/chunk-method/one-03.svg new file mode 100644 index 000000000..11754e506 --- /dev/null +++ b/web/src/assets/svg/chunk-method/one-03.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/one-04.svg b/web/src/assets/svg/chunk-method/one-04.svg new file mode 100644 index 000000000..a5ead4e90 --- /dev/null +++ b/web/src/assets/svg/chunk-method/one-04.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/paper-01.svg b/web/src/assets/svg/chunk-method/paper-01.svg index 7619e0222..54e39f8e3 100644 --- a/web/src/assets/svg/chunk-method/paper-01.svg +++ b/web/src/assets/svg/chunk-method/paper-01.svg @@ -1,102 +1,96 @@ - + - + fill="url(#paint0_radial_912_25822)" /> - - - - - - - - - - + + + + + + + + + + - + - + - - + - - - - - - - - - + - - - - - - - - - - - + - + - - + - + - + - + - + \ No newline at end of file diff --git a/web/src/assets/svg/chunk-method/paper-02.svg b/web/src/assets/svg/chunk-method/paper-02.svg index 857994efb..e23d41444 100644 --- a/web/src/assets/svg/chunk-method/paper-02.svg +++ b/web/src/assets/svg/chunk-method/paper-02.svg @@ -1,82 +1,80 @@ - + - + fill="url(#paint0_radial_912_25830)" /> - - - - - - - - - - + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + - + - - + - + - + - + - + \ No newline at end of file diff --git a/web/src/components/max-token-number.tsx b/web/src/components/max-token-number.tsx new file mode 100644 index 000000000..70eb44c19 --- /dev/null +++ b/web/src/components/max-token-number.tsx @@ -0,0 +1,32 @@ +import { Flex, Form, InputNumber, Slider } from 'antd'; + +const MaxTokenNumber = () => { + return ( + + + + + + + + + + + + + ); +}; + +export default MaxTokenNumber; diff --git a/web/src/hooks/documentHooks.ts b/web/src/hooks/documentHooks.ts index 536da8bd2..f3b75bf77 100644 --- a/web/src/hooks/documentHooks.ts +++ b/web/src/hooks/documentHooks.ts @@ -1,4 +1,5 @@ import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge'; +import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; import { api_host } from '@/utils/api'; import { buildChunkHighlights } from '@/utils/documentUtils'; import { useCallback, useMemo } from 'react'; @@ -117,7 +118,11 @@ export const useSetDocumentParser = () => { const { knowledgeId } = useGetKnowledgeSearchParams(); const setDocumentParser = useCallback( - (parserId: string, documentId: string) => { + ( + parserId: string, + documentId: string, + parserConfig: IChangeParserConfigRequestBody, + ) => { try { return dispatch({ type: 'kFModel/document_change_parser', @@ -125,6 +130,7 @@ export const useSetDocumentParser = () => { parser_id: parserId, doc_id: documentId, kb_id: knowledgeId, + parser_config: parserConfig, }, }); } catch (errorInfo) { diff --git a/web/src/interfaces/database/knowledge.ts b/web/src/interfaces/database/knowledge.ts index 415c29808..654f59702 100644 --- a/web/src/interfaces/database/knowledge.ts +++ b/web/src/interfaces/database/knowledge.ts @@ -28,6 +28,12 @@ export interface Parserconfig { to_page: number; } +export interface IKnowledgeFileParserConfig { + chunk_token_num: number; + layout_recognize: boolean; + pages: number[][]; + task_page_size: number; +} export interface IKnowledgeFile { chunk_num: number; create_date: string; @@ -51,6 +57,7 @@ export interface IKnowledgeFile { type: string; update_date: string; update_time: number; + parser_config: IKnowledgeFileParserConfig; } export interface ITenantInfo { diff --git a/web/src/interfaces/request/document.ts b/web/src/interfaces/request/document.ts new file mode 100644 index 000000000..5ecdb57f0 --- /dev/null +++ b/web/src/interfaces/request/document.ts @@ -0,0 +1,12 @@ +export interface IChangeParserConfigRequestBody { + pages: number[][]; + chunk_token_num: number; + layout_recognize: boolean; + task_page_size: number; +} + +export interface IChangeParserRequestBody { + parser_id: string; + doc_id: string; + parser_config: IChangeParserConfigRequestBody; +} diff --git a/web/src/pages/add-knowledge/components/knowledge-file/chunk-method-modal.tsx b/web/src/pages/add-knowledge/components/knowledge-file/chunk-method-modal.tsx index 69d5e9168..12654335f 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/chunk-method-modal.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/chunk-method-modal.tsx @@ -1,10 +1,23 @@ import { IModalManagerChildrenProps } from '@/components/modal-manager'; import { - useFetchTenantInfo, - useSelectParserList, -} from '@/hooks/userSettingHook'; -import { Modal, Space, Tag } from 'antd'; -import React, { useEffect, useState } from 'react'; + Button, + Divider, + Form, + InputNumber, + Modal, + Space, + Switch, + Tag, +} from 'antd'; +import React, { useEffect, useMemo } from 'react'; + +import MaxTokenNumber from '@/components/max-token-number'; +import { IKnowledgeFileParserConfig } from '@/interfaces/database/knowledge'; +import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; +import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; +import omit from 'lodash/omit'; +import {} from 'module'; +import { useFetchParserListOnMount } from './hooks'; import styles from './index.less'; @@ -12,41 +25,74 @@ const { CheckableTag } = Tag; interface IProps extends Omit { loading: boolean; - onOk: (parserId: string) => void; + onOk: ( + parserId: string, + parserConfig: IChangeParserConfigRequestBody, + ) => void; showModal?(): void; - parser_id: string; + parserId: string; + parserConfig: IKnowledgeFileParserConfig; + documentType: string; } +const hidePagesChunkMethods = ['qa', 'table', 'picture', 'resume', 'one']; + const ChunkMethodModal: React.FC = ({ - parser_id, + parserId, onOk, hideModal, visible, + documentType, + parserConfig, }) => { - const [selectedTag, setSelectedTag] = useState(''); - const parserList = useSelectParserList(); - - useFetchTenantInfo(); - - useEffect(() => { - setSelectedTag(parser_id); - }, [parser_id]); + const { parserList, handleChange, selectedTag } = + useFetchParserListOnMount(parserId); + const [form] = Form.useForm(); const handleOk = async () => { - onOk(selectedTag); + const values = await form.validateFields(); + console.info(values); + const parser_config = { + ...values.parser_config, + pages: values.pages?.map((x: any) => [x.from, x.to]) ?? [], + }; + console.info(parser_config); + onOk(selectedTag, parser_config); }; - const handleChange = (tag: string, checked: boolean) => { - const nextSelectedTag = checked ? tag : selectedTag; - setSelectedTag(nextSelectedTag); + const showPages = useMemo(() => { + return ( + documentType === 'pdf' && + hidePagesChunkMethods.every((x) => x !== selectedTag) + ); + }, [documentType, selectedTag]); + + const showOne = useMemo(() => { + return showPages || selectedTag === 'one'; + }, [showPages, selectedTag]); + + const afterClose = () => { + form.resetFields(); }; + useEffect(() => { + if (visible) { + const pages = + parserConfig.pages?.map((x) => ({ from: x[0], to: x[1] })) ?? []; + form.setFieldsValue({ + pages: pages.length > 0 ? pages : [{ from: 1, to: 1024 }], + parser_config: omit(parserConfig, 'pages'), + }); + } + }, [form, parserConfig, visible]); + return (
@@ -63,6 +109,138 @@ const ChunkMethodModal: React.FC = ({ })}
+ + { +
+ {showPages && ( + <> + + {(fields, { add, remove }) => ( + <> + {fields.map(({ key, name, ...restField }) => ( + + 0 ? [name - 1, 'to'] : []} + rules={[ + { + required: true, + message: 'Missing start page number', + }, + ({ getFieldValue }) => ({ + validator(_, value) { + if ( + name === 0 || + !value || + getFieldValue(['pages', name - 1, 'to']) < + value + ) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + 'The current value must be greater than the previous to!', + ), + ); + }, + }), + ]} + > + + + ({ + validator(_, value) { + if ( + !value || + getFieldValue(['pages', name, 'from']) < value + ) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + 'The current value must be greater than to!', + ), + ); + }, + }), + ]} + > + + + {name > 0 && ( + remove(name)} /> + )} + + ))} + + + + + )} + + + + + + )} + {showOne && ( + + + + )} + {selectedTag === 'naive' && } +
+ }
); }; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/hooks.ts b/web/src/pages/add-knowledge/components/knowledge-file/hooks.ts index 3618908b4..f560954e9 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/hooks.ts +++ b/web/src/pages/add-knowledge/components/knowledge-file/hooks.ts @@ -7,9 +7,13 @@ import { } from '@/hooks/documentHooks'; import { useGetKnowledgeSearchParams } from '@/hooks/routeHook'; import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; -import { useFetchTenantInfo } from '@/hooks/userSettingHook'; +import { + useFetchTenantInfo, + useSelectParserList, +} from '@/hooks/userSettingHook'; import { Pagination } from '@/interfaces/common'; import { IKnowledgeFile } from '@/interfaces/database/knowledge'; +import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; import { PaginationProps } from 'antd'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { useDispatch, useNavigate, useSelector } from 'umi'; @@ -222,8 +226,8 @@ export const useChangeDocumentParser = (documentId: string) => { ]); const onChangeParserOk = useCallback( - async (parserId: string) => { - const ret = await setDocumentParser(parserId, documentId); + async (parserId: string, parserConfig: IChangeParserConfigRequestBody) => { + const ret = await setDocumentParser(parserId, documentId, parserConfig); if (ret === 0) { hideChangeParserModal(); } @@ -239,3 +243,21 @@ export const useChangeDocumentParser = (documentId: string) => { showChangeParserModal, }; }; + +export const useFetchParserListOnMount = (parserId: string) => { + const [selectedTag, setSelectedTag] = useState(''); + const parserList = useSelectParserList(); + + useFetchTenantInfo(); + + useEffect(() => { + setSelectedTag(parserId); + }, [parserId]); + + const handleChange = (tag: string, checked: boolean) => { + const nextSelectedTag = checked ? tag : selectedTag; + setSelectedTag(nextSelectedTag); + }; + + return { parserList, handleChange, selectedTag }; +}; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/index.less b/web/src/pages/add-knowledge/components/knowledge-file/index.less index 402299745..a2d22eaf0 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/index.less +++ b/web/src/pages/add-knowledge/components/knowledge-file/index.less @@ -34,3 +34,7 @@ .tochunks { cursor: pointer; } + +.pageInputNumber { + width: 220px; +} diff --git a/web/src/pages/add-knowledge/components/knowledge-file/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/index.tsx index 7c36b6c1b..1859baee4 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/index.tsx @@ -224,7 +224,9 @@ const KnowledgeFile = () => { onOk={onCreateOk} /> = { namespace: 'kFModel', state: { - isShowCEFwModal: false, - isShowTntModal: false, - isShowSegmentSetModal: false, - isShowRenameModal: false, tenantIfo: {}, data: [], total: 0, @@ -43,9 +35,7 @@ const model: DvaModel = { ...payload, }; }, - setIsShowRenameModal(state, { payload }) { - return { ...state, isShowRenameModal: payload }; - }, + setCurrentRecord(state, { payload }) { return { ...state, currentRecord: payload }; }, @@ -120,7 +110,7 @@ const model: DvaModel = { const { retcode } = data; if (retcode === 0) { message.success('Modified!'); - put({ + yield put({ type: 'getKfList', payload: { kb_id: payload.kb_id }, }); @@ -148,10 +138,7 @@ const model: DvaModel = { const { retcode } = data; if (retcode === 0) { message.success('rename success!'); - yield put({ - type: 'setIsShowRenameModal', - payload: false, - }); + yield put({ type: 'getKfList', payload: { kb_id: payload.kb_id }, @@ -164,16 +151,11 @@ const model: DvaModel = { const { data } = yield call(kbService.document_create, payload); const { retcode } = data; if (retcode === 0) { - put({ + yield put({ type: 'getKfList', payload: { kb_id: payload.kb_id }, }); - put({ - type: 'kFModel/updateState', - payload: { - isShowCEFwModal: false, - }, - }); + message.success('Created!'); } return retcode; @@ -202,16 +184,11 @@ const model: DvaModel = { ); const { retcode } = data; if (retcode === 0) { - put({ + yield put({ type: 'getKfList', payload: { kb_id: payload.kb_id }, }); - put({ - type: 'updateState', - payload: { - isShowSegmentSetModal: false, - }, - }); + message.success('Modified!'); } return retcode; diff --git a/web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx b/web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx index fc8d056aa..96991c572 100644 --- a/web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx @@ -1,22 +1,12 @@ import { normFile } from '@/utils/fileUtil'; import { PlusOutlined } from '@ant-design/icons'; -import { - Button, - Flex, - Form, - Input, - InputNumber, - Radio, - Select, - Slider, - Space, - Upload, -} from 'antd'; +import { Button, Form, Input, Radio, Select, Space, Upload } from 'antd'; import { useFetchKnowledgeConfigurationOnMount, useSubmitKnowledgeConfiguration, } from './hooks'; +import MaxTokenNumber from '@/components/max-token-number'; import { FormInstance } from 'antd/lib'; import styles from './index.less'; @@ -121,35 +111,7 @@ const ConfigurationForm = ({ form }: { form: FormInstance }) => { const parserId = getFieldValue('parser_id'); if (parserId === 'naive') { - return ( - - - - - - - - - - - - - ); + return ; } return null; }} diff --git a/web/src/pages/add-knowledge/components/knowledge-setting/model.ts b/web/src/pages/add-knowledge/components/knowledge-setting/model.ts index 29126cc9b..a24aea8f4 100644 --- a/web/src/pages/add-knowledge/components/knowledge-setting/model.ts +++ b/web/src/pages/add-knowledge/components/knowledge-setting/model.ts @@ -5,7 +5,6 @@ import { DvaModel } from 'umi'; export interface KSModelState { isShowPSwModal: boolean; - isShowTntModal: boolean; tenantIfo: any; knowledgeDetails: IKnowledge; } @@ -14,7 +13,6 @@ const model: DvaModel = { namespace: 'kSModel', state: { isShowPSwModal: false, - isShowTntModal: false, tenantIfo: {}, knowledgeDetails: {} as any, }, diff --git a/web/src/pages/add-knowledge/components/knowledge-setting/utils.ts b/web/src/pages/add-knowledge/components/knowledge-setting/utils.ts index 9cb8cd055..e92c0a9ba 100644 --- a/web/src/pages/add-knowledge/components/knowledge-setting/utils.ts +++ b/web/src/pages/add-knowledge/components/knowledge-setting/utils.ts @@ -5,9 +5,9 @@ const getImageName = (prefix: string, length: number) => export const ImageMap = { book: getImageName('book', 4), - laws: getImageName('law', 4), + laws: getImageName('law', 2), manual: getImageName('manual', 4), - picture: getImageName('picture', 2), + picture: getImageName('media', 2), naive: getImageName('naive', 2), paper: getImageName('paper', 2), presentation: getImageName('presentation', 2), @@ -32,10 +32,13 @@ export const TextMap = { The chunk granularity is consistent with 'ARTICLE', and all the upper level text will be included in the chunk.

`, }, - manual: { title: '', description: `

Only PDF is supported.

+ manual: { + title: '', + description: `

Only PDF is supported.

We assume manual has hierarchical section structure. We use the lowest section titles as pivots to slice documents. So, the figures and tables in the same section will not be sliced apart, and chunk size might be large. -

` }, +

`, + }, naive: { title: '', description: `

Supported file formats are DOCX, EXCEL, PPT, IMAGE, PDF, TXT.

@@ -100,19 +103,19 @@ export const TextMap = {
  • Every row in table will be treated as a chunk.
  • `, -}, -picture: { - title: '', - description: ` + }, + picture: { + title: '', + description: `

    Image files are supported. Video is coming soon.

    If the picture has text in it, OCR is applied to extract the text as its text description.

    If the text extracted by OCR is not enough, visual LLM is used to get the descriptions.

    `, }, -one: { - title: '', - description: ` + one: { + title: '', + description: `

    Supported file formats are DOCX, EXCEL, PDF, TXT.

    For a document, it will be treated as an entire chunk, no split at all. diff --git a/web/src/pages/add-knowledge/model.ts b/web/src/pages/add-knowledge/model.ts index accfd7bc4..637e309a4 100644 --- a/web/src/pages/add-knowledge/model.ts +++ b/web/src/pages/add-knowledge/model.ts @@ -1,7 +1,6 @@ import { DvaModel } from 'umi'; export interface kAModelState { isShowPSwModal: boolean; - isShowTntModal: boolean; tenantIfo: any; id: string; doc_id: string; @@ -11,7 +10,6 @@ const model: DvaModel = { namespace: 'kAModel', state: { isShowPSwModal: false, - isShowTntModal: false, tenantIfo: {}, id: '', doc_id: '', diff --git a/web/src/pages/setting/CPwModal.tsx b/web/src/pages/setting/CPwModal.tsx deleted file mode 100644 index c9713709d..000000000 --- a/web/src/pages/setting/CPwModal.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { rsaPsw } from '@/utils'; -import { Form, Input, Modal } from 'antd'; -import { useTranslation } from 'react-i18next'; -import { useDispatch, useSelector } from 'umi'; - -type FieldType = { - newPassword?: string; - password?: string; -}; - -const CpwModal = () => { - const dispatch = useDispatch(); - const settingModel = useSelector((state: any) => state.settingModel); - const { isShowPSwModal } = settingModel; - const { t } = useTranslation(); - const [form] = Form.useForm(); - - const handleCancel = () => { - dispatch({ - type: 'settingModel/updateState', - payload: { - isShowPSwModal: false, - }, - }); - }; - const handleOk = async () => { - try { - const values = await form.validateFields(); - var password = rsaPsw(values.password); - var new_password = rsaPsw(values.newPassword); - - dispatch({ - type: 'settingModel/setting', - payload: { - password, - new_password, - }, - }); - } catch (errorInfo) { - console.log('Failed:', errorInfo); - } - }; - - return ( - -

    - - label="旧密码" - name="password" - rules={[{ required: true, message: 'Please input value' }]} - > - - - - label="新密码" - name="newPassword" - rules={[ - { required: true, message: 'Please input your newPassword!' }, - ]} - > - - - - - ); -}; -export default CpwModal; diff --git a/web/src/pages/setting/List.tsx b/web/src/pages/setting/List.tsx deleted file mode 100644 index b86a380df..000000000 --- a/web/src/pages/setting/List.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import { useTranslation } from 'react-i18next'; - -import { useEffect, useState } from 'react'; -import styles from './index.less'; - -import { RadarChartOutlined } from '@ant-design/icons'; -import { ProCard } from '@ant-design/pro-components'; -import { Button, Card, Col, Row, Tag } from 'antd'; -import { useDispatch, useSelector } from 'umi'; - -interface DataType { - key: React.Key; - name: string; - age: number; - address: string; - description: string; -} - -const SettingList = () => { - const dispatch = useDispatch(); - const settingModel = useSelector((state: any) => state.settingModel); - const { llmInfo = {}, factoriesList, myLlm = [] } = settingModel; - const { OpenAI = [], tongyi = [] } = llmInfo; - const [collapsed, setCollapsed] = useState(true); - const { t } = useTranslation(); - - useEffect(() => { - dispatch({ - type: 'settingModel/factories_list', - payload: {}, - }); - dispatch({ - type: 'settingModel/llm_list', - payload: {}, - }); - dispatch({ - type: 'settingModel/my_llm', - payload: {}, - }); - }, [dispatch]); - - return ( -
    - {myLlm.map((item: any) => { - return ( - 可折叠-图标自定义
    } - collapsibleIconRender={({ - collapsed: buildInCollapsed, - }: { - collapsed: boolean; - }) => { - return ( -
    -

    - - {item.llm_factory} -

    -
    - {item.tags.split(',').map((d: string) => { - return {d}; - })} -
    - {buildInCollapsed ? ( - 显示{OpenAI.length}个模型 - ) : ( - 收起{OpenAI.length}个模型 - )} -
    - ); - }} - extra={ - - } - style={{ marginBlockStart: 16 }} - headerBordered - collapsible - defaultCollapsed - > - ); - })} - - - {factoriesList.map((item: any) => { - return ( - - { - e.stopPropagation(); - dispatch({ - type: 'settingModel/updateState', - payload: { - llm_factory: item.name, - isShowSAKModal: true, - }, - }); - }} - > - 设置 - - } - > -
    - {item.tags.split(',').map((d: string) => { - return {d}; - })} -
    -
    - - ); - })} -
    - - ); -}; -export default SettingList; diff --git a/web/src/pages/setting/SAKModal.tsx b/web/src/pages/setting/SAKModal.tsx deleted file mode 100644 index 43744cb12..000000000 --- a/web/src/pages/setting/SAKModal.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { Form, Input, Modal } from 'antd'; -import { useTranslation } from 'react-i18next'; -import { useDispatch, useSelector } from 'umi'; - -type FieldType = { - api_key?: string; -}; - -const SakModal = () => { - const dispatch = useDispatch(); - const settingModel = useSelector((state: any) => state.settingModel); - const { isShowSAKModal, llm_factory } = settingModel; - const { t } = useTranslation(); - const [form] = Form.useForm(); - - const handleCancel = () => { - dispatch({ - type: 'settingModel/updateState', - payload: { - isShowSAKModal: false, - }, - }); - }; - const handleOk = async () => { - try { - const values = await form.validateFields(); - - dispatch({ - type: 'settingModel/set_api_key', - payload: { - api_key: values.api_key, - llm_factory: llm_factory, - }, - }); - } catch (errorInfo) { - console.log('Failed:', errorInfo); - } - }; - - return ( - -
    - - label="API Key" - name="api_key" - rules={[{ required: true, message: 'Please input ' }]} - > - - - -
    - ); -}; -export default SakModal; diff --git a/web/src/pages/setting/SSModal.tsx b/web/src/pages/setting/SSModal.tsx deleted file mode 100644 index 6e89669b4..000000000 --- a/web/src/pages/setting/SSModal.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import { Form, Modal, Select } from 'antd'; -import { useTranslation } from 'react-i18next'; -import { useDispatch, useSelector } from 'umi'; - -type FieldType = { - embd_id?: string; - img2txt_id?: string; - llm_id?: string; - asr_id?: string; -}; - -const SsModal = () => { - const dispatch = useDispatch(); - const settingModel = useSelector((state: any) => state.settingModel); - const { isShowSSModal, llmInfo = {}, tenantIfo } = settingModel; - const [form] = Form.useForm(); - const { t } = useTranslation(); - - const handleCancel = () => { - dispatch({ - type: 'settingModel/updateState', - payload: { - isShowSSModal: false, - }, - }); - }; - - const handleOk = async () => { - try { - const values = await form.validateFields(); - const retcode = await dispatch({ - type: 'settingModel/set_tenant_info', - payload: { - ...values, - tenant_id: tenantIfo.tenant_id, - }, - }); - retcode === 0 && - dispatch({ - type: 'settingModel/updateState', - payload: { - isShowSSModal: false, - }, - }); - } catch (errorInfo) { - console.log('Failed:', errorInfo); - } - }; - - const handleChange = () => {}; - - return ( - -
    - - label="embedding 模型" - name="embd_id" - rules={[{ required: true, message: 'Please input value' }]} - initialValue={tenantIfo.embd_id} - > - { - const options = llmInfo[t] - .filter((d: any) => d.model_type === 'chat') - .map((d: any) => ({ label: d.llm_name, value: d.llm_name })); - return { label: t, options }; - })} - /> - - - label="image2text 模型" - name="img2txt_id" - rules={[{ required: true, message: 'Please input value' }]} - initialValue={tenantIfo.img2txt_id} - > - { - const options = llmInfo[t] - .filter((d: any) => d.model_type === 'speech2text') - .map((d: any) => ({ label: d.llm_name, value: d.llm_name })); - return { label: t, options }; - })} - /> - - -
    - ); -}; -export default SsModal; diff --git a/web/src/pages/setting/TntModal.tsx b/web/src/pages/setting/TntModal.tsx deleted file mode 100644 index 72a5ef809..000000000 --- a/web/src/pages/setting/TntModal.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; -import { Modal, Table } from 'antd'; -import { ColumnsType } from 'antd/es/table'; -import { useTranslation } from 'react-i18next'; -import { useDispatch, useSelector } from 'umi'; -import styles from './index.less'; - -interface DataType { - key: React.Key; - name: string; - role: string; - time: string; -} - -const TntModal = () => { - const dispatch = useDispatch(); - const settingModel = useSelector((state: any) => state.settingModel); - const { isShowTntModal, tenantIfo, factoriesList } = settingModel; - const { t } = useTranslation(); - const loading = useOneNamespaceEffectsLoading('settingModel', [ - 'getTenantInfo', - ]); - - const columns: ColumnsType = [ - { title: '姓名', dataIndex: 'name', key: 'name' }, - { title: '活动时间', dataIndex: 'update_date', key: 'update_date' }, - { title: '角色', dataIndex: 'role', key: 'age' }, - ]; - - const handleCancel = () => { - dispatch({ - type: 'settingModel/updateState', - payload: { - isShowTntModal: false, - }, - }); - }; - - const handleOk = async () => { - dispatch({ - type: 'settingModel/updateState', - payload: { - isShowTntModal: false, - }, - }); - }; - - return ( - -
    {tenantIfo.name}
    - - - ); -}; -export default TntModal; diff --git a/web/src/pages/setting/index.less b/web/src/pages/setting/index.less deleted file mode 100644 index 5904ac850..000000000 --- a/web/src/pages/setting/index.less +++ /dev/null @@ -1,49 +0,0 @@ -.settingPage { - padding: 10px; -} - -.avatar { - display: flex; - justify-content: center; -} - -.tenantIfo { - height: 50px; - background-color: #f4dfdf; - margin-bottom: 10px; - padding: 5px; - box-sizing: border-box; - display: flex; - align-items: center; -} - -.list { - :global { - .ant-pro-card-header { - height: 150px; - background-color: rgb(229, 231, 235); - } - } -} - -ul { - li { - display: flex; - justify-content: space-between; - margin-bottom: 5px; - - .statusDisaabled { - width: 10px; - height: 10px; - border-radius: 40%; - background: rgba(0, 0, 0, 0.4); - } - - .statusAvailable { - width: 10px; - height: 10px; - border-radius: 50%; - background: green; - } - } -} \ No newline at end of file diff --git a/web/src/pages/setting/index.tsx b/web/src/pages/setting/index.tsx deleted file mode 100644 index dbb6bccc1..000000000 --- a/web/src/pages/setting/index.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { Button, FloatButton } from 'antd'; -import i18n from 'i18next'; -import { useTranslation } from 'react-i18next'; - -import authorizationUtil from '@/utils/authorizationUtil'; -import { useEffect } from 'react'; -import { useDispatch, useSelector } from 'umi'; -import CPwModal from './CPwModal'; -import List from './List'; -import SAKModal from './SAKModal'; -import SSModal from './SSModal'; -import TntModal from './TntModal'; -import styles from './index.less'; - -const Setting = () => { - const dispatch = useDispatch(); - const settingModel = useSelector((state: any) => state.settingModel); - const { t } = useTranslation(); - const userInfo = authorizationUtil.getUserInfoObject(); - - const changeLang = (val: string) => { - // 改变状态里的 语言 进行切换 - i18n.changeLanguage(val); - }; - - useEffect(() => { - dispatch({ - type: 'settingModel/getTenantInfo', - payload: {}, - }); - }, []); - - const showCPwModal = () => { - dispatch({ - type: 'settingModel/updateState', - payload: { - isShowPSwModal: true, - }, - }); - }; - const showTntModal = () => { - dispatch({ - type: 'settingModel/updateState', - payload: { - isShowTntModal: true, - }, - }); - }; - const showSSModal = () => { - dispatch({ - type: 'settingModel/updateState', - payload: { - isShowSSModal: true, - }, - }); - }; - return ( -
    -
    - -
    -
    账号:{userInfo.name}
    -
    - 密码:****** - -
    -
    -
    -
    - - - -
    - - - - - i18n.changeLanguage(i18n.language == 'en' ? 'zh' : 'en')} - type="default" - style={{ right: 94, fontSize: 14 }} - /> -
    - ); -}; -export default Setting; diff --git a/web/src/pages/setting/model.ts b/web/src/pages/user-setting/model.ts similarity index 96% rename from web/src/pages/setting/model.ts rename to web/src/pages/user-setting/model.ts index 6e628ded8..0caa12f33 100644 --- a/web/src/pages/setting/model.ts +++ b/web/src/pages/user-setting/model.ts @@ -1,151 +1,151 @@ -import { ITenantInfo } from '@/interfaces/database/knowledge'; -import { - IFactory, - IMyLlmValue, - IThirdOAIModelCollection as IThirdAiModelCollection, -} from '@/interfaces/database/llm'; -import { IUserInfo } from '@/interfaces/database/userSetting'; -import userService from '@/services/userService'; -import { message } from 'antd'; -import { DvaModel } from 'umi'; - -export interface SettingModelState { - llm_factory: string; - tenantIfo: Nullable; - llmInfo: IThirdAiModelCollection; - myLlmList: Record; - factoryList: IFactory[]; - userInfo: IUserInfo; -} - -const model: DvaModel = { - namespace: 'settingModel', - state: { - llm_factory: '', - tenantIfo: null, - llmInfo: {}, - myLlmList: {}, - factoryList: [], - userInfo: {} as IUserInfo, - }, - reducers: { - updateState(state, { payload }) { - return { - ...state, - ...payload, - }; - }, - setUserInfo(state, { payload }) { - return { - ...state, - userInfo: payload, - }; - }, - }, - effects: { - *setting({ payload = {} }, { call, put }) { - const { data } = yield call(userService.setting, payload); - const { retcode } = data; - if (retcode === 0) { - message.success('Modified!'); - yield put({ - type: 'getUserInfo', - }); - } - }, - *getUserInfo({ payload = {} }, { call, put }) { - const { data } = yield call(userService.user_info, payload); - const { retcode, data: res } = data; - - // const userInfo = { - // avatar: res.avatar, - // name: res.nickname, - // email: res.email, - // }; - // authorizationUtil.setUserInfo(userInfo); - if (retcode === 0) { - yield put({ type: 'setUserInfo', payload: res }); - // localStorage.setItem('userInfo',res.) - } - }, - *getTenantInfo({ payload = {} }, { call, put }) { - const { data } = yield call(userService.get_tenant_info, payload); - const { retcode, data: res } = data; - // llm_id 对应chat_id - // asr_id 对应speech2txt - - if (retcode === 0) { - res.chat_id = res.llm_id; - res.speech2text_id = res.asr_id; - yield put({ - type: 'updateState', - payload: { - tenantIfo: res, - }, - }); - } - }, - *set_tenant_info({ payload = {} }, { call, put }) { - const { data } = yield call(userService.set_tenant_info, payload); - const { retcode } = data; - if (retcode === 0) { - message.success('Modified!'); - yield put({ - type: 'getTenantInfo', - }); - } - return retcode; - }, - - *factories_list({ payload = {} }, { call, put }) { - const { data } = yield call(userService.factories_list); - const { retcode, data: res } = data; - if (retcode === 0) { - yield put({ - type: 'updateState', - payload: { - factoryList: res, - }, - }); - } - }, - *llm_list({ payload = {} }, { call, put }) { - const { data } = yield call(userService.llm_list, payload); - const { retcode, data: res } = data; - if (retcode === 0) { - yield put({ - type: 'updateState', - payload: { - llmInfo: res, - }, - }); - } - }, - *my_llm({ payload = {} }, { call, put }) { - const { data } = yield call(userService.my_llm); - const { retcode, data: res } = data; - if (retcode === 0) { - yield put({ - type: 'updateState', - payload: { - myLlmList: res, - }, - }); - } - }, - *set_api_key({ payload = {} }, { call, put }) { - const { data } = yield call(userService.set_api_key, payload); - const { retcode } = data; - if (retcode === 0) { - message.success('Modified!'); - yield put({ type: 'my_llm' }); - yield put({ type: 'factories_list' }); - yield put({ - type: 'updateState', - }); - } - return retcode; - }, - }, -}; -export default model; +import { ITenantInfo } from '@/interfaces/database/knowledge'; +import { + IFactory, + IMyLlmValue, + IThirdOAIModelCollection as IThirdAiModelCollection, +} from '@/interfaces/database/llm'; +import { IUserInfo } from '@/interfaces/database/userSetting'; +import userService from '@/services/userService'; +import { message } from 'antd'; +import { DvaModel } from 'umi'; + +export interface SettingModelState { + llm_factory: string; + tenantIfo: Nullable; + llmInfo: IThirdAiModelCollection; + myLlmList: Record; + factoryList: IFactory[]; + userInfo: IUserInfo; +} + +const model: DvaModel = { + namespace: 'settingModel', + state: { + llm_factory: '', + tenantIfo: null, + llmInfo: {}, + myLlmList: {}, + factoryList: [], + userInfo: {} as IUserInfo, + }, + reducers: { + updateState(state, { payload }) { + return { + ...state, + ...payload, + }; + }, + setUserInfo(state, { payload }) { + return { + ...state, + userInfo: payload, + }; + }, + }, + effects: { + *setting({ payload = {} }, { call, put }) { + const { data } = yield call(userService.setting, payload); + const { retcode } = data; + if (retcode === 0) { + message.success('Modified!'); + yield put({ + type: 'getUserInfo', + }); + } + }, + *getUserInfo({ payload = {} }, { call, put }) { + const { data } = yield call(userService.user_info, payload); + const { retcode, data: res } = data; + + // const userInfo = { + // avatar: res.avatar, + // name: res.nickname, + // email: res.email, + // }; + // authorizationUtil.setUserInfo(userInfo); + if (retcode === 0) { + yield put({ type: 'setUserInfo', payload: res }); + // localStorage.setItem('userInfo',res.) + } + }, + *getTenantInfo({ payload = {} }, { call, put }) { + const { data } = yield call(userService.get_tenant_info, payload); + const { retcode, data: res } = data; + // llm_id 对应chat_id + // asr_id 对应speech2txt + + if (retcode === 0) { + res.chat_id = res.llm_id; + res.speech2text_id = res.asr_id; + yield put({ + type: 'updateState', + payload: { + tenantIfo: res, + }, + }); + } + }, + *set_tenant_info({ payload = {} }, { call, put }) { + const { data } = yield call(userService.set_tenant_info, payload); + const { retcode } = data; + if (retcode === 0) { + message.success('Modified!'); + yield put({ + type: 'getTenantInfo', + }); + } + return retcode; + }, + + *factories_list({ payload = {} }, { call, put }) { + const { data } = yield call(userService.factories_list); + const { retcode, data: res } = data; + if (retcode === 0) { + yield put({ + type: 'updateState', + payload: { + factoryList: res, + }, + }); + } + }, + *llm_list({ payload = {} }, { call, put }) { + const { data } = yield call(userService.llm_list, payload); + const { retcode, data: res } = data; + if (retcode === 0) { + yield put({ + type: 'updateState', + payload: { + llmInfo: res, + }, + }); + } + }, + *my_llm({ payload = {} }, { call, put }) { + const { data } = yield call(userService.my_llm); + const { retcode, data: res } = data; + if (retcode === 0) { + yield put({ + type: 'updateState', + payload: { + myLlmList: res, + }, + }); + } + }, + *set_api_key({ payload = {} }, { call, put }) { + const { data } = yield call(userService.set_api_key, payload); + const { retcode } = data; + if (retcode === 0) { + message.success('Modified!'); + yield put({ type: 'my_llm' }); + yield put({ type: 'factories_list' }); + yield put({ + type: 'updateState', + }); + } + return retcode; + }, + }, +}; +export default model; diff --git a/web/src/routes.ts b/web/src/routes.ts index 0a3018ac4..b6d9e9bcc 100644 --- a/web/src/routes.ts +++ b/web/src/routes.ts @@ -52,10 +52,6 @@ const routes = [ path: '/chat', component: '@/pages/chat', }, - { - path: '/setting', - component: '@/pages/setting', - }, { path: '/user-setting', component: '@/pages/user-setting',