balibabu
commited on
Commit
·
f3d0ebd
1
Parent(s):
53be70c
feat: remove KnowledgeSearching and add knowledge configuration page and add a run button to the document (#64)
Browse files* feat: add a run button to the document
* feat: add knowledge configuration page
* feat: remove KnowledgeSearching
- web/src/assets/svg/refresh.svg +5 -0
- web/src/assets/svg/run.svg +15 -0
- web/src/constants/knowledge.ts +5 -6
- web/src/hooks/knowledgeHook.ts +49 -2
- web/src/interfaces/database/llm.ts +16 -0
- web/src/pages/add-knowledge/components/knowledge-chunk/index.less +1 -0
- web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx +13 -25
- web/src/pages/add-knowledge/components/knowledge-file/index.tsx +2 -42
- web/src/pages/add-knowledge/components/knowledge-file/model.ts +27 -31
- web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.less +9 -0
- web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx +47 -16
- web/src/pages/add-knowledge/components/knowledge-search/index.less +0 -79
- web/src/pages/add-knowledge/components/knowledge-search/index.tsx +0 -276
- web/src/pages/add-knowledge/components/knowledge-search/model.ts +0 -160
- web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx +217 -0
- web/src/pages/add-knowledge/components/knowledge-setting/index.less +23 -17
- web/src/pages/add-knowledge/components/knowledge-setting/index.tsx +8 -4
- web/src/pages/add-knowledge/components/knowledge-setting/model.ts +13 -9
- web/src/pages/add-knowledge/components/knowledge-sidebar/index.tsx +12 -12
- web/src/pages/setting/model.ts +4 -3
- web/src/routes.ts +0 -4
- web/src/utils/fileUtil.ts +28 -0
web/src/assets/svg/refresh.svg
ADDED
|
web/src/assets/svg/run.svg
ADDED
|
web/src/constants/knowledge.ts
CHANGED
@@ -2,13 +2,12 @@ export enum KnowledgeRouteKey {
|
|
2 |
Dataset = 'dataset',
|
3 |
Testing = 'testing',
|
4 |
Configuration = 'configuration',
|
5 |
-
TempTesting = 'tempTesting',
|
6 |
}
|
7 |
|
8 |
export enum RunningStatus {
|
9 |
-
UNSTART = '0',
|
10 |
-
RUNNING = '1',
|
11 |
-
CANCEL = '2',
|
12 |
-
DONE = '3',
|
13 |
-
FAIL = '4',
|
14 |
}
|
|
|
2 |
Dataset = 'dataset',
|
3 |
Testing = 'testing',
|
4 |
Configuration = 'configuration',
|
|
|
5 |
}
|
6 |
|
7 |
export enum RunningStatus {
|
8 |
+
UNSTART = '0', // need to run
|
9 |
+
RUNNING = '1', // need to cancel
|
10 |
+
CANCEL = '2', // need to refresh
|
11 |
+
DONE = '3', // need to refresh
|
12 |
+
FAIL = '4', // need to refresh
|
13 |
}
|
web/src/hooks/knowledgeHook.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
import showDeleteConfirm from '@/components/deleting-confirm';
|
2 |
-
import { IKnowledge } from '@/interfaces/database/knowledge';
|
3 |
-
import { useCallback } from 'react';
|
4 |
import { useDispatch, useSearchParams, useSelector } from 'umi';
|
5 |
|
6 |
export const useKnowledgeBaseId = (): string => {
|
@@ -77,3 +77,50 @@ export const useDeleteChunkByIds = (): {
|
|
77 |
removeChunk: onRemoveChunk,
|
78 |
};
|
79 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import showDeleteConfirm from '@/components/deleting-confirm';
|
2 |
+
import { IKnowledge, ITenantInfo } from '@/interfaces/database/knowledge';
|
3 |
+
import { useCallback, useEffect, useMemo } from 'react';
|
4 |
import { useDispatch, useSearchParams, useSelector } from 'umi';
|
5 |
|
6 |
export const useKnowledgeBaseId = (): string => {
|
|
|
77 |
removeChunk: onRemoveChunk,
|
78 |
};
|
79 |
};
|
80 |
+
|
81 |
+
export const useSelectParserList = (): Array<{
|
82 |
+
value: string;
|
83 |
+
label: string;
|
84 |
+
}> => {
|
85 |
+
const tenantIfo: Nullable<ITenantInfo> = useSelector(
|
86 |
+
(state: any) => state.settingModel.tenantIfo,
|
87 |
+
);
|
88 |
+
|
89 |
+
const parserList = useMemo(() => {
|
90 |
+
const parserArray: Array<string> = tenantIfo?.parser_ids.split(',') ?? [];
|
91 |
+
return parserArray.map((x) => {
|
92 |
+
const arr = x.split(':');
|
93 |
+
return { value: arr[0], label: arr[1] };
|
94 |
+
});
|
95 |
+
}, [tenantIfo]);
|
96 |
+
|
97 |
+
return parserList;
|
98 |
+
};
|
99 |
+
|
100 |
+
export const useFetchParserList = () => {
|
101 |
+
const dispatch = useDispatch();
|
102 |
+
|
103 |
+
useEffect(() => {
|
104 |
+
dispatch({
|
105 |
+
type: 'settingModel/getTenantInfo',
|
106 |
+
});
|
107 |
+
}, [dispatch]);
|
108 |
+
};
|
109 |
+
|
110 |
+
export const useFetchKnowledgeBaseConfiguration = () => {
|
111 |
+
const dispatch = useDispatch();
|
112 |
+
const knowledgeBaseId = useKnowledgeBaseId();
|
113 |
+
|
114 |
+
const fetchKnowledgeBaseConfiguration = useCallback(() => {
|
115 |
+
dispatch({
|
116 |
+
type: 'kSModel/getKbDetail',
|
117 |
+
payload: {
|
118 |
+
kb_id: knowledgeBaseId,
|
119 |
+
},
|
120 |
+
});
|
121 |
+
}, [dispatch, knowledgeBaseId]);
|
122 |
+
|
123 |
+
useEffect(() => {
|
124 |
+
fetchKnowledgeBaseConfiguration();
|
125 |
+
}, [fetchKnowledgeBaseConfiguration]);
|
126 |
+
};
|
web/src/interfaces/database/llm.ts
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export interface IThirdOAIModel {
|
2 |
+
available: boolean;
|
3 |
+
create_date: string;
|
4 |
+
create_time: number;
|
5 |
+
fid: string;
|
6 |
+
id: number;
|
7 |
+
llm_name: string;
|
8 |
+
max_tokens: number;
|
9 |
+
model_type: string;
|
10 |
+
status: string;
|
11 |
+
tags: string;
|
12 |
+
update_date: string;
|
13 |
+
update_time: number;
|
14 |
+
}
|
15 |
+
|
16 |
+
export type IThirdOAIModelCollection = Record<string, IThirdOAIModel[]>;
|
web/src/pages/add-knowledge/components/knowledge-chunk/index.less
CHANGED
@@ -26,6 +26,7 @@
|
|
26 |
.chunkContainer {
|
27 |
height: calc(100vh - 320px);
|
28 |
overflow: auto;
|
|
|
29 |
}
|
30 |
|
31 |
.pageFooter {
|
|
|
26 |
.chunkContainer {
|
27 |
height: calc(100vh - 320px);
|
28 |
overflow: auto;
|
29 |
+
width: 100%;
|
30 |
}
|
31 |
|
32 |
.pageFooter {
|
web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx
CHANGED
@@ -2,10 +2,11 @@ import { ReactComponent as SelectFilesEndIcon } from '@/assets/svg/select-files-
|
|
2 |
import { ReactComponent as SelectFilesStartIcon } from '@/assets/svg/select-files-start.svg';
|
3 |
import {
|
4 |
useDeleteDocumentById,
|
|
|
5 |
useGetDocumentDefaultParser,
|
6 |
useKnowledgeBaseId,
|
|
|
7 |
} from '@/hooks/knowledgeHook';
|
8 |
-
import { ITenantInfo } from '@/interfaces/database/knowledge';
|
9 |
import uploadService from '@/services/uploadService';
|
10 |
import {
|
11 |
ArrowLeftOutlined,
|
@@ -28,9 +29,8 @@ import {
|
|
28 |
UploadProps,
|
29 |
} from 'antd';
|
30 |
import classNames from 'classnames';
|
31 |
-
import { ReactElement, useEffect,
|
32 |
-
import {
|
33 |
-
import { Link, useDispatch, useNavigate, useSelector } from 'umi';
|
34 |
|
35 |
import { KnowledgeRouteKey } from '@/constants/knowledge';
|
36 |
import styles from './index.less';
|
@@ -45,13 +45,11 @@ const UploaderItem = ({
|
|
45 |
file,
|
46 |
actions,
|
47 |
isUpload,
|
48 |
-
parserArray,
|
49 |
}: {
|
50 |
isUpload: boolean;
|
51 |
originNode: ReactElement;
|
52 |
file: UploadFile;
|
53 |
fileList: object[];
|
54 |
-
parserArray: string[];
|
55 |
actions: { download: Function; preview: Function; remove: any };
|
56 |
}) => {
|
57 |
const { parserConfig, defaultParserId } = useGetDocumentDefaultParser(
|
@@ -63,12 +61,7 @@ const UploaderItem = ({
|
|
63 |
|
64 |
const documentId = file?.response?.id;
|
65 |
|
66 |
-
const parserList =
|
67 |
-
return parserArray.map((x) => {
|
68 |
-
const arr = x.split(':');
|
69 |
-
return { value: arr[0], label: arr[1] };
|
70 |
-
});
|
71 |
-
}, [parserArray]);
|
72 |
|
73 |
const saveParser = (parserId: string) => {
|
74 |
dispatch({
|
@@ -154,14 +147,10 @@ const KnowledgeUploadFile = () => {
|
|
154 |
const knowledgeBaseId = useKnowledgeBaseId();
|
155 |
const [isUpload, setIsUpload] = useState(true);
|
156 |
const dispatch = useDispatch();
|
157 |
-
|
158 |
-
(state: any) => state.settingModel.tenantIfo,
|
159 |
-
);
|
160 |
const navigate = useNavigate();
|
161 |
const fileListRef = useRef<UploadFile[]>([]);
|
162 |
|
163 |
-
const parserArray = tenantIfo?.parser_ids.split(',') ?? [];
|
164 |
-
|
165 |
const createRequest: (props: UploadRequestOption) => void = async function ({
|
166 |
file,
|
167 |
onSuccess,
|
@@ -170,9 +159,13 @@ const KnowledgeUploadFile = () => {
|
|
170 |
}) {
|
171 |
const { data } = await uploadService.uploadFile(file, knowledgeBaseId);
|
172 |
if (data.retcode === 0) {
|
173 |
-
|
|
|
|
|
174 |
} else {
|
175 |
-
|
|
|
|
|
176 |
}
|
177 |
};
|
178 |
|
@@ -188,7 +181,6 @@ const KnowledgeUploadFile = () => {
|
|
188 |
fileList={fileList}
|
189 |
originNode={originNode}
|
190 |
actions={actions}
|
191 |
-
parserArray={parserArray}
|
192 |
></UploaderItem>
|
193 |
);
|
194 |
},
|
@@ -215,11 +207,7 @@ const KnowledgeUploadFile = () => {
|
|
215 |
}
|
216 |
};
|
217 |
|
218 |
-
|
219 |
-
dispatch({
|
220 |
-
type: 'settingModel/getTenantInfo',
|
221 |
-
});
|
222 |
-
}, []);
|
223 |
|
224 |
return (
|
225 |
<div className={styles.uploadWrapper}>
|
|
|
2 |
import { ReactComponent as SelectFilesStartIcon } from '@/assets/svg/select-files-start.svg';
|
3 |
import {
|
4 |
useDeleteDocumentById,
|
5 |
+
useFetchParserList,
|
6 |
useGetDocumentDefaultParser,
|
7 |
useKnowledgeBaseId,
|
8 |
+
useSelectParserList,
|
9 |
} from '@/hooks/knowledgeHook';
|
|
|
10 |
import uploadService from '@/services/uploadService';
|
11 |
import {
|
12 |
ArrowLeftOutlined,
|
|
|
29 |
UploadProps,
|
30 |
} from 'antd';
|
31 |
import classNames from 'classnames';
|
32 |
+
import { ReactElement, useEffect, useRef, useState } from 'react';
|
33 |
+
import { Link, useDispatch, useNavigate } from 'umi';
|
|
|
34 |
|
35 |
import { KnowledgeRouteKey } from '@/constants/knowledge';
|
36 |
import styles from './index.less';
|
|
|
45 |
file,
|
46 |
actions,
|
47 |
isUpload,
|
|
|
48 |
}: {
|
49 |
isUpload: boolean;
|
50 |
originNode: ReactElement;
|
51 |
file: UploadFile;
|
52 |
fileList: object[];
|
|
|
53 |
actions: { download: Function; preview: Function; remove: any };
|
54 |
}) => {
|
55 |
const { parserConfig, defaultParserId } = useGetDocumentDefaultParser(
|
|
|
61 |
|
62 |
const documentId = file?.response?.id;
|
63 |
|
64 |
+
const parserList = useSelectParserList();
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
const saveParser = (parserId: string) => {
|
67 |
dispatch({
|
|
|
147 |
const knowledgeBaseId = useKnowledgeBaseId();
|
148 |
const [isUpload, setIsUpload] = useState(true);
|
149 |
const dispatch = useDispatch();
|
150 |
+
|
|
|
|
|
151 |
const navigate = useNavigate();
|
152 |
const fileListRef = useRef<UploadFile[]>([]);
|
153 |
|
|
|
|
|
154 |
const createRequest: (props: UploadRequestOption) => void = async function ({
|
155 |
file,
|
156 |
onSuccess,
|
|
|
159 |
}) {
|
160 |
const { data } = await uploadService.uploadFile(file, knowledgeBaseId);
|
161 |
if (data.retcode === 0) {
|
162 |
+
if (onSuccess) {
|
163 |
+
onSuccess(data.data);
|
164 |
+
}
|
165 |
} else {
|
166 |
+
if (onError) {
|
167 |
+
onError(data.data);
|
168 |
+
}
|
169 |
}
|
170 |
};
|
171 |
|
|
|
181 |
fileList={fileList}
|
182 |
originNode={originNode}
|
183 |
actions={actions}
|
|
|
184 |
></UploaderItem>
|
185 |
);
|
186 |
},
|
|
|
207 |
}
|
208 |
};
|
209 |
|
210 |
+
useFetchParserList();
|
|
|
|
|
|
|
|
|
211 |
|
212 |
return (
|
213 |
<div className={styles.uploadWrapper}>
|
web/src/pages/add-knowledge/components/knowledge-file/index.tsx
CHANGED
@@ -1,8 +1,5 @@
|
|
1 |
import { KnowledgeRouteKey } from '@/constants/knowledge';
|
2 |
-
import {
|
3 |
-
useDeleteDocumentById,
|
4 |
-
useKnowledgeBaseId,
|
5 |
-
} from '@/hooks/knowledgeHook';
|
6 |
import { Pagination } from '@/interfaces/common';
|
7 |
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
|
8 |
import { getOneNamespaceEffectsLoading } from '@/utils/storeUtil';
|
@@ -40,7 +37,6 @@ const KnowledgeFile = () => {
|
|
40 |
const effects = useSelector((state: any) => state.loading.effects);
|
41 |
const { data, total } = kFModel;
|
42 |
const knowledgeBaseId = useKnowledgeBaseId();
|
43 |
-
const { removeDocument } = useDeleteDocumentById();
|
44 |
|
45 |
const loading = getOneNamespaceEffectsLoading('kFModel', effects, [
|
46 |
'getKfList',
|
@@ -132,9 +128,7 @@ const KnowledgeFile = () => {
|
|
132 |
},
|
133 |
});
|
134 |
};
|
135 |
-
|
136 |
-
removeDocument(doc_id);
|
137 |
-
};
|
138 |
const showCEFModal = () => {
|
139 |
dispatch({
|
140 |
type: 'kFModel/updateState',
|
@@ -144,15 +138,6 @@ const KnowledgeFile = () => {
|
|
144 |
});
|
145 |
};
|
146 |
|
147 |
-
const showSegmentSetModal = () => {
|
148 |
-
dispatch({
|
149 |
-
type: 'kFModel/updateState',
|
150 |
-
payload: {
|
151 |
-
isShowSegmentSetModal: true,
|
152 |
-
},
|
153 |
-
});
|
154 |
-
};
|
155 |
-
|
156 |
const actionItems: MenuProps['items'] = useMemo(() => {
|
157 |
return [
|
158 |
{
|
@@ -185,31 +170,6 @@ const KnowledgeFile = () => {
|
|
185 |
},
|
186 |
];
|
187 |
}, []);
|
188 |
-
const chunkItems: MenuProps['items'] = [
|
189 |
-
{
|
190 |
-
key: '1',
|
191 |
-
label: (
|
192 |
-
<div>
|
193 |
-
<Button type="link" onClick={showSegmentSetModal}>
|
194 |
-
{' '}
|
195 |
-
分段设置
|
196 |
-
</Button>
|
197 |
-
</div>
|
198 |
-
),
|
199 |
-
},
|
200 |
-
{
|
201 |
-
key: '2',
|
202 |
-
label: (
|
203 |
-
<div>
|
204 |
-
<Button type="link" onClick={onRmDocument}>
|
205 |
-
{' '}
|
206 |
-
Delete
|
207 |
-
</Button>
|
208 |
-
</div>
|
209 |
-
),
|
210 |
-
// disabled: true,
|
211 |
-
},
|
212 |
-
];
|
213 |
|
214 |
const toChunk = (id: string) => {
|
215 |
navigate(
|
|
|
1 |
import { KnowledgeRouteKey } from '@/constants/knowledge';
|
2 |
+
import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
|
|
|
|
|
|
|
3 |
import { Pagination } from '@/interfaces/common';
|
4 |
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
|
5 |
import { getOneNamespaceEffectsLoading } from '@/utils/storeUtil';
|
|
|
37 |
const effects = useSelector((state: any) => state.loading.effects);
|
38 |
const { data, total } = kFModel;
|
39 |
const knowledgeBaseId = useKnowledgeBaseId();
|
|
|
40 |
|
41 |
const loading = getOneNamespaceEffectsLoading('kFModel', effects, [
|
42 |
'getKfList',
|
|
|
128 |
},
|
129 |
});
|
130 |
};
|
131 |
+
|
|
|
|
|
132 |
const showCEFModal = () => {
|
133 |
dispatch({
|
134 |
type: 'kFModel/updateState',
|
|
|
138 |
});
|
139 |
};
|
140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
const actionItems: MenuProps['items'] = useMemo(() => {
|
142 |
return [
|
143 |
{
|
|
|
170 |
},
|
171 |
];
|
172 |
}, []);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
|
174 |
const toChunk = (id: string) => {
|
175 |
navigate(
|
web/src/pages/add-knowledge/components/knowledge-file/model.ts
CHANGED
@@ -55,33 +55,23 @@ const model: DvaModel<KFModelState> = {
|
|
55 |
return { ...state, pagination: { ...state.pagination, ...payload } };
|
56 |
},
|
57 |
},
|
58 |
-
subscriptions: {
|
59 |
-
setup({ dispatch, history }) {
|
60 |
-
history.listen((location) => {});
|
61 |
-
},
|
62 |
-
},
|
63 |
effects: {
|
64 |
-
*createKf({ payload = {} }, { call
|
65 |
-
const { data
|
66 |
-
const { retcode
|
67 |
if (retcode === 0) {
|
68 |
message.success('创建成功!');
|
69 |
}
|
70 |
},
|
71 |
-
*updateKf({ payload = {} }, { call
|
72 |
-
const { data
|
73 |
-
const { retcode
|
74 |
if (retcode === 0) {
|
75 |
message.success('修改成功!');
|
76 |
}
|
77 |
},
|
78 |
-
*getKfDetail({ payload = {}
|
79 |
-
const { data
|
80 |
-
const { retcode, data: res, retmsg } = data;
|
81 |
-
if (retcode === 0) {
|
82 |
-
// localStorage.setItem('userInfo',res.)
|
83 |
-
callback && callback(res);
|
84 |
-
}
|
85 |
},
|
86 |
*getKfList({ payload = {} }, { call, put, select }) {
|
87 |
const state: KFModelState = yield select((state: any) => state.kFModel);
|
@@ -119,11 +109,11 @@ const model: DvaModel<KFModelState> = {
|
|
119 |
{ type: 'poll', delay: 5000 }, // TODO: Provide type support for this effect
|
120 |
],
|
121 |
*updateDocumentStatus({ payload = {} }, { call, put }) {
|
122 |
-
const { data
|
123 |
kbService.document_change_status,
|
124 |
pick(payload, ['doc_id', 'status']),
|
125 |
);
|
126 |
-
const { retcode
|
127 |
if (retcode === 0) {
|
128 |
message.success('修改成功!');
|
129 |
put({
|
@@ -133,10 +123,10 @@ const model: DvaModel<KFModelState> = {
|
|
133 |
}
|
134 |
},
|
135 |
*document_rm({ payload = {} }, { call, put }) {
|
136 |
-
const { data
|
137 |
doc_id: payload.doc_id,
|
138 |
});
|
139 |
-
const { retcode
|
140 |
if (retcode === 0) {
|
141 |
message.success('删除成功!');
|
142 |
yield put({
|
@@ -151,7 +141,7 @@ const model: DvaModel<KFModelState> = {
|
|
151 |
kbService.document_rename,
|
152 |
omit(payload, ['kb_id']),
|
153 |
);
|
154 |
-
const { retcode
|
155 |
if (retcode === 0) {
|
156 |
message.success('rename success!');
|
157 |
yield put({
|
@@ -168,7 +158,7 @@ const model: DvaModel<KFModelState> = {
|
|
168 |
},
|
169 |
*document_create({ payload = {} }, { call, put }) {
|
170 |
const { data } = yield call(kbService.document_create, payload);
|
171 |
-
const { retcode
|
172 |
if (retcode === 0) {
|
173 |
put({
|
174 |
type: 'kFModel/updateState',
|
@@ -181,19 +171,25 @@ const model: DvaModel<KFModelState> = {
|
|
181 |
return retcode;
|
182 |
},
|
183 |
*document_run({ payload = {} }, { call, put }) {
|
184 |
-
const { data } = yield call(
|
|
|
|
|
|
|
185 |
const { retcode } = data;
|
186 |
if (retcode === 0) {
|
187 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
}
|
189 |
return retcode;
|
190 |
},
|
191 |
*document_change_parser({ payload = {} }, { call, put }) {
|
192 |
-
const { data
|
193 |
-
|
194 |
-
payload,
|
195 |
-
);
|
196 |
-
const { retcode, data: res, retmsg } = data;
|
197 |
if (retcode === 0) {
|
198 |
put({
|
199 |
type: 'updateState',
|
|
|
55 |
return { ...state, pagination: { ...state.pagination, ...payload } };
|
56 |
},
|
57 |
},
|
|
|
|
|
|
|
|
|
|
|
58 |
effects: {
|
59 |
+
*createKf({ payload = {} }, { call }) {
|
60 |
+
const { data } = yield call(kbService.createKb, payload);
|
61 |
+
const { retcode } = data;
|
62 |
if (retcode === 0) {
|
63 |
message.success('创建成功!');
|
64 |
}
|
65 |
},
|
66 |
+
*updateKf({ payload = {} }, { call }) {
|
67 |
+
const { data } = yield call(kbService.updateKb, payload);
|
68 |
+
const { retcode } = data;
|
69 |
if (retcode === 0) {
|
70 |
message.success('修改成功!');
|
71 |
}
|
72 |
},
|
73 |
+
*getKfDetail({ payload = {} }, { call }) {
|
74 |
+
const { data } = yield call(kbService.get_kb_detail, payload);
|
|
|
|
|
|
|
|
|
|
|
75 |
},
|
76 |
*getKfList({ payload = {} }, { call, put, select }) {
|
77 |
const state: KFModelState = yield select((state: any) => state.kFModel);
|
|
|
109 |
{ type: 'poll', delay: 5000 }, // TODO: Provide type support for this effect
|
110 |
],
|
111 |
*updateDocumentStatus({ payload = {} }, { call, put }) {
|
112 |
+
const { data } = yield call(
|
113 |
kbService.document_change_status,
|
114 |
pick(payload, ['doc_id', 'status']),
|
115 |
);
|
116 |
+
const { retcode } = data;
|
117 |
if (retcode === 0) {
|
118 |
message.success('修改成功!');
|
119 |
put({
|
|
|
123 |
}
|
124 |
},
|
125 |
*document_rm({ payload = {} }, { call, put }) {
|
126 |
+
const { data } = yield call(kbService.document_rm, {
|
127 |
doc_id: payload.doc_id,
|
128 |
});
|
129 |
+
const { retcode } = data;
|
130 |
if (retcode === 0) {
|
131 |
message.success('删除成功!');
|
132 |
yield put({
|
|
|
141 |
kbService.document_rename,
|
142 |
omit(payload, ['kb_id']),
|
143 |
);
|
144 |
+
const { retcode } = data;
|
145 |
if (retcode === 0) {
|
146 |
message.success('rename success!');
|
147 |
yield put({
|
|
|
158 |
},
|
159 |
*document_create({ payload = {} }, { call, put }) {
|
160 |
const { data } = yield call(kbService.document_create, payload);
|
161 |
+
const { retcode } = data;
|
162 |
if (retcode === 0) {
|
163 |
put({
|
164 |
type: 'kFModel/updateState',
|
|
|
171 |
return retcode;
|
172 |
},
|
173 |
*document_run({ payload = {} }, { call, put }) {
|
174 |
+
const { data } = yield call(
|
175 |
+
kbService.document_run,
|
176 |
+
omit(payload, ['knowledgeBaseId']),
|
177 |
+
);
|
178 |
const { retcode } = data;
|
179 |
if (retcode === 0) {
|
180 |
+
if (payload.knowledgeBaseId) {
|
181 |
+
yield put({
|
182 |
+
type: 'getKfList',
|
183 |
+
payload: { kb_id: payload.knowledgeBaseId },
|
184 |
+
});
|
185 |
+
}
|
186 |
+
message.success('Operation successfully !');
|
187 |
}
|
188 |
return retcode;
|
189 |
},
|
190 |
*document_change_parser({ payload = {} }, { call, put }) {
|
191 |
+
const { data } = yield call(kbService.document_change_parser, payload);
|
192 |
+
const { retcode } = data;
|
|
|
|
|
|
|
193 |
if (retcode === 0) {
|
194 |
put({
|
195 |
type: 'updateState',
|
web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.less
CHANGED
@@ -1,3 +1,12 @@
|
|
1 |
.popover-content {
|
2 |
width: 300px;
|
3 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
.popover-content {
|
2 |
width: 300px;
|
3 |
}
|
4 |
+
|
5 |
+
.operationIcon {
|
6 |
+
text-align: center;
|
7 |
+
margin-right: 20%;
|
8 |
+
width: 20px;
|
9 |
+
&:hover {
|
10 |
+
cursor: pointer;
|
11 |
+
}
|
12 |
+
}
|
web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx
CHANGED
@@ -1,9 +1,21 @@
|
|
|
|
|
|
1 |
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
|
2 |
import { Badge, DescriptionsProps, Flex, Popover, Space, Tag } from 'antd';
|
3 |
import { RunningStatus, RunningStatusMap } from '../constant';
|
4 |
|
|
|
|
|
5 |
import styles from './index.less';
|
6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
interface IProps {
|
8 |
record: IKnowledgeFile;
|
9 |
}
|
@@ -31,7 +43,7 @@ const PopoverContent = ({ record }: IProps) => {
|
|
31 |
<Flex vertical className={styles['popover-content']}>
|
32 |
{items.map((x) => {
|
33 |
return (
|
34 |
-
<div>
|
35 |
<b>{x.label}:</b>
|
36 |
<p>{x.children}</p>
|
37 |
</div>
|
@@ -42,27 +54,46 @@ const PopoverContent = ({ record }: IProps) => {
|
|
42 |
};
|
43 |
|
44 |
export const ParsingStatusCell = ({ record }: IProps) => {
|
|
|
45 |
const text = record.run;
|
46 |
const runningStatus = RunningStatusMap[text];
|
47 |
|
48 |
const isRunning = text === RunningStatus.RUNNING;
|
49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
return (
|
51 |
-
<
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
{
|
56 |
-
|
57 |
-
<
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
|
|
|
|
|
|
|
|
|
|
66 |
);
|
67 |
};
|
68 |
|
|
|
1 |
+
import { ReactComponent as RefreshIcon } from '@/assets/svg/refresh.svg';
|
2 |
+
import { ReactComponent as RunIcon } from '@/assets/svg/run.svg';
|
3 |
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
|
4 |
import { Badge, DescriptionsProps, Flex, Popover, Space, Tag } from 'antd';
|
5 |
import { RunningStatus, RunningStatusMap } from '../constant';
|
6 |
|
7 |
+
import { CloseCircleOutlined } from '@ant-design/icons';
|
8 |
+
import { useDispatch } from 'umi';
|
9 |
import styles from './index.less';
|
10 |
|
11 |
+
const iconMap = {
|
12 |
+
[RunningStatus.UNSTART]: RunIcon,
|
13 |
+
[RunningStatus.RUNNING]: CloseCircleOutlined,
|
14 |
+
[RunningStatus.CANCEL]: RefreshIcon,
|
15 |
+
[RunningStatus.DONE]: RefreshIcon,
|
16 |
+
[RunningStatus.FAIL]: RefreshIcon,
|
17 |
+
};
|
18 |
+
|
19 |
interface IProps {
|
20 |
record: IKnowledgeFile;
|
21 |
}
|
|
|
43 |
<Flex vertical className={styles['popover-content']}>
|
44 |
{items.map((x) => {
|
45 |
return (
|
46 |
+
<div key={x.key}>
|
47 |
<b>{x.label}:</b>
|
48 |
<p>{x.children}</p>
|
49 |
</div>
|
|
|
54 |
};
|
55 |
|
56 |
export const ParsingStatusCell = ({ record }: IProps) => {
|
57 |
+
const dispatch = useDispatch();
|
58 |
const text = record.run;
|
59 |
const runningStatus = RunningStatusMap[text];
|
60 |
|
61 |
const isRunning = text === RunningStatus.RUNNING;
|
62 |
|
63 |
+
const OperationIcon = iconMap[text];
|
64 |
+
|
65 |
+
const handleOperationIconClick = () => {
|
66 |
+
dispatch({
|
67 |
+
type: 'kFModel/document_run',
|
68 |
+
payload: {
|
69 |
+
doc_ids: [record.id],
|
70 |
+
run: isRunning ? 2 : 1,
|
71 |
+
knowledgeBaseId: record.kb_id,
|
72 |
+
},
|
73 |
+
});
|
74 |
+
};
|
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>
|
84 |
+
<Badge color={runningStatus.color} />
|
85 |
+
{runningStatus.label}
|
86 |
+
<span>{(record.progress * 100).toFixed(2)}%</span>
|
87 |
+
</Space>
|
88 |
+
) : (
|
89 |
+
runningStatus.label
|
90 |
+
)}
|
91 |
+
</Tag>
|
92 |
+
</Popover>
|
93 |
+
<div onClick={handleOperationIconClick} className={styles.operationIcon}>
|
94 |
+
<OperationIcon />
|
95 |
+
</div>
|
96 |
+
</Flex>
|
97 |
);
|
98 |
};
|
99 |
|
web/src/pages/add-knowledge/components/knowledge-search/index.less
DELETED
@@ -1,79 +0,0 @@
|
|
1 |
-
.chunkPage {
|
2 |
-
padding: 24px;
|
3 |
-
display: flex;
|
4 |
-
height: calc(100vh - 112px);
|
5 |
-
// flex-direction: column;
|
6 |
-
|
7 |
-
.filter {
|
8 |
-
margin-right: 20px;
|
9 |
-
display: flex;
|
10 |
-
height: 32px;
|
11 |
-
width: 300px;
|
12 |
-
flex-wrap: wrap;
|
13 |
-
justify-content: space-between;
|
14 |
-
}
|
15 |
-
|
16 |
-
.pageContainer {
|
17 |
-
flex: 1;
|
18 |
-
display: flex;
|
19 |
-
flex-direction: column;
|
20 |
-
|
21 |
-
.pageContent {
|
22 |
-
flex: 1;
|
23 |
-
width: 100%;
|
24 |
-
padding-right: 12px;
|
25 |
-
overflow-y: auto;
|
26 |
-
|
27 |
-
.spin {
|
28 |
-
min-height: 400px;
|
29 |
-
}
|
30 |
-
}
|
31 |
-
|
32 |
-
.pageFooter {
|
33 |
-
height: 32px;
|
34 |
-
float: right;
|
35 |
-
}
|
36 |
-
}
|
37 |
-
|
38 |
-
}
|
39 |
-
|
40 |
-
.container {
|
41 |
-
height: 100px;
|
42 |
-
display: flex;
|
43 |
-
flex-direction: column;
|
44 |
-
justify-content: space-between;
|
45 |
-
|
46 |
-
.content {
|
47 |
-
display: flex;
|
48 |
-
justify-content: space-between;
|
49 |
-
|
50 |
-
.context {
|
51 |
-
flex: 1;
|
52 |
-
// width: 207px;
|
53 |
-
height: 88px;
|
54 |
-
overflow: hidden;
|
55 |
-
}
|
56 |
-
}
|
57 |
-
|
58 |
-
.footer {
|
59 |
-
height: 20px;
|
60 |
-
|
61 |
-
.text {
|
62 |
-
margin-left: 10px;
|
63 |
-
}
|
64 |
-
}
|
65 |
-
}
|
66 |
-
|
67 |
-
.card {
|
68 |
-
:global {
|
69 |
-
.ant-card-body {
|
70 |
-
padding: 10px;
|
71 |
-
margin: 0;
|
72 |
-
}
|
73 |
-
|
74 |
-
margin-bottom: 10px;
|
75 |
-
}
|
76 |
-
|
77 |
-
cursor: pointer;
|
78 |
-
|
79 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
web/src/pages/add-knowledge/components/knowledge-search/index.tsx
DELETED
@@ -1,276 +0,0 @@
|
|
1 |
-
import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
|
2 |
-
import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
|
3 |
-
import { api_host } from '@/utils/api';
|
4 |
-
import { DeleteOutlined, MinusSquareOutlined } from '@ant-design/icons';
|
5 |
-
import type { PaginationProps } from 'antd';
|
6 |
-
import {
|
7 |
-
Card,
|
8 |
-
Col,
|
9 |
-
Input,
|
10 |
-
Pagination,
|
11 |
-
Popconfirm,
|
12 |
-
Row,
|
13 |
-
Select,
|
14 |
-
Spin,
|
15 |
-
Switch,
|
16 |
-
} from 'antd';
|
17 |
-
import { debounce } from 'lodash';
|
18 |
-
import React, { useCallback, useEffect } from 'react';
|
19 |
-
import { useDispatch, useSelector } from 'umi';
|
20 |
-
import CreateModal from '../knowledge-chunk/components/chunk-creating-modal';
|
21 |
-
|
22 |
-
import styles from './index.less';
|
23 |
-
|
24 |
-
const KnowledgeSearching = () => {
|
25 |
-
const dispatch = useDispatch();
|
26 |
-
const kSearchModel = useSelector((state: any) => state.kSearchModel);
|
27 |
-
const chunkModel = useSelector((state: any) => state.chunkModel);
|
28 |
-
const loading = useOneNamespaceEffectsLoading('kSearchModel', [
|
29 |
-
'chunk_list',
|
30 |
-
'switch_chunk',
|
31 |
-
]);
|
32 |
-
const knowledgeBaseId = useKnowledgeBaseId();
|
33 |
-
|
34 |
-
const {
|
35 |
-
data = [],
|
36 |
-
total,
|
37 |
-
d_list = [],
|
38 |
-
question,
|
39 |
-
doc_ids,
|
40 |
-
pagination,
|
41 |
-
} = kSearchModel;
|
42 |
-
const { chunk_id, doc_id, isShowCreateModal } = chunkModel;
|
43 |
-
|
44 |
-
const getChunkList = () => {
|
45 |
-
dispatch({
|
46 |
-
type: 'kSearchModel/chunk_list',
|
47 |
-
payload: {
|
48 |
-
kb_id: knowledgeBaseId,
|
49 |
-
},
|
50 |
-
});
|
51 |
-
};
|
52 |
-
const confirm = (id: string) => {
|
53 |
-
dispatch({
|
54 |
-
type: 'kSearchModel/rm_chunk',
|
55 |
-
payload: {
|
56 |
-
chunk_ids: [id],
|
57 |
-
kb_id: knowledgeBaseId,
|
58 |
-
},
|
59 |
-
});
|
60 |
-
};
|
61 |
-
const handleEditchunk = (item: any) => {
|
62 |
-
const { chunk_id, doc_id } = item;
|
63 |
-
dispatch({
|
64 |
-
type: 'chunkModel/updateState',
|
65 |
-
payload: {
|
66 |
-
isShowCreateModal: true,
|
67 |
-
chunk_id,
|
68 |
-
doc_id,
|
69 |
-
},
|
70 |
-
});
|
71 |
-
getChunkList();
|
72 |
-
};
|
73 |
-
const onShowSizeChange: PaginationProps['onShowSizeChange'] = (
|
74 |
-
page,
|
75 |
-
size,
|
76 |
-
) => {
|
77 |
-
dispatch({
|
78 |
-
type: 'kSearchModel/updateState',
|
79 |
-
payload: {
|
80 |
-
pagination: { page, size },
|
81 |
-
},
|
82 |
-
});
|
83 |
-
};
|
84 |
-
useEffect(() => {
|
85 |
-
dispatch({
|
86 |
-
type: 'kSearchModel/updateState',
|
87 |
-
payload: {
|
88 |
-
doc_ids: [],
|
89 |
-
question: '',
|
90 |
-
},
|
91 |
-
});
|
92 |
-
dispatch({
|
93 |
-
type: 'kSearchModel/getKfList',
|
94 |
-
payload: {
|
95 |
-
kb_id: knowledgeBaseId,
|
96 |
-
},
|
97 |
-
});
|
98 |
-
}, []);
|
99 |
-
const switchChunk = (item: any, available_int: boolean) => {
|
100 |
-
const { chunk_id, doc_id } = item;
|
101 |
-
|
102 |
-
dispatch({
|
103 |
-
type: 'kSearchModel/switch_chunk',
|
104 |
-
payload: {
|
105 |
-
chunk_ids: [chunk_id],
|
106 |
-
doc_id,
|
107 |
-
available_int,
|
108 |
-
kb_id: knowledgeBaseId,
|
109 |
-
},
|
110 |
-
});
|
111 |
-
};
|
112 |
-
|
113 |
-
useEffect(() => {
|
114 |
-
getChunkList();
|
115 |
-
}, [doc_ids, pagination, question]);
|
116 |
-
const debounceChange = debounce((value) => {
|
117 |
-
dispatch({
|
118 |
-
type: 'kSearchModel/updateState',
|
119 |
-
payload: {
|
120 |
-
question: value,
|
121 |
-
},
|
122 |
-
});
|
123 |
-
}, 300);
|
124 |
-
|
125 |
-
const debounceCallback = useCallback(
|
126 |
-
(value: string) => debounceChange(value),
|
127 |
-
[],
|
128 |
-
);
|
129 |
-
const handleInputChange = (
|
130 |
-
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
131 |
-
) => {
|
132 |
-
const value = e.target.value;
|
133 |
-
debounceCallback(value);
|
134 |
-
};
|
135 |
-
const handleSelectChange = (value: any[]) => {
|
136 |
-
dispatch({
|
137 |
-
type: 'kSearchModel/updateState',
|
138 |
-
payload: {
|
139 |
-
doc_ids: value,
|
140 |
-
},
|
141 |
-
});
|
142 |
-
};
|
143 |
-
|
144 |
-
return (
|
145 |
-
<>
|
146 |
-
<div className={styles.chunkPage}>
|
147 |
-
<div className={styles.filter}>
|
148 |
-
<Select
|
149 |
-
showSearch
|
150 |
-
placeholder="文件列表"
|
151 |
-
optionFilterProp="children"
|
152 |
-
onChange={handleSelectChange}
|
153 |
-
style={{ width: 300, marginBottom: 20 }}
|
154 |
-
options={d_list}
|
155 |
-
fieldNames={{ label: 'name', value: 'id' }}
|
156 |
-
mode="multiple"
|
157 |
-
/>
|
158 |
-
|
159 |
-
<Input.TextArea
|
160 |
-
autoSize={{ minRows: 6, maxRows: 6 }}
|
161 |
-
placeholder="搜索"
|
162 |
-
style={{ width: 300 }}
|
163 |
-
allowClear
|
164 |
-
onChange={handleInputChange}
|
165 |
-
/>
|
166 |
-
</div>
|
167 |
-
<div className={styles.pageContainer}>
|
168 |
-
<div className={styles.pageContent}>
|
169 |
-
<Spin spinning={loading} className={styles.spin} size="large">
|
170 |
-
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24 }}>
|
171 |
-
{data.map((item: any) => {
|
172 |
-
return (
|
173 |
-
<Col
|
174 |
-
className="gutter-row"
|
175 |
-
key={item.chunk_id}
|
176 |
-
xs={24}
|
177 |
-
sm={12}
|
178 |
-
md={12}
|
179 |
-
lg={8}
|
180 |
-
>
|
181 |
-
<Card
|
182 |
-
className={styles.card}
|
183 |
-
onClick={() => {
|
184 |
-
handleEditchunk(item);
|
185 |
-
}}
|
186 |
-
>
|
187 |
-
<img
|
188 |
-
style={{ width: '50px' }}
|
189 |
-
src={`${api_host}/document/image/${item.img_id}`}
|
190 |
-
alt=""
|
191 |
-
/>
|
192 |
-
<div className={styles.container}>
|
193 |
-
<div className={styles.content}>
|
194 |
-
<span className={styles.context}>
|
195 |
-
{item.content_ltks}
|
196 |
-
</span>
|
197 |
-
<span className={styles.delete}>
|
198 |
-
<Switch
|
199 |
-
size="small"
|
200 |
-
defaultValue={item.doc_ids == '1'}
|
201 |
-
onChange={(checked: boolean, e: any) => {
|
202 |
-
e.stopPropagation();
|
203 |
-
e.nativeEvent.stopImmediatePropagation();
|
204 |
-
switchChunk(item, checked);
|
205 |
-
}}
|
206 |
-
/>
|
207 |
-
</span>
|
208 |
-
</div>
|
209 |
-
<div className={styles.footer}>
|
210 |
-
<span className={styles.text}>
|
211 |
-
<MinusSquareOutlined />
|
212 |
-
{item.doc_num}文档
|
213 |
-
</span>
|
214 |
-
<span className={styles.text}>
|
215 |
-
<MinusSquareOutlined />
|
216 |
-
{item.chunk_num}个
|
217 |
-
</span>
|
218 |
-
<span className={styles.text}>
|
219 |
-
<MinusSquareOutlined />
|
220 |
-
{item.token_num}千字符
|
221 |
-
</span>
|
222 |
-
<span style={{ float: 'right' }}>
|
223 |
-
<Popconfirm
|
224 |
-
title="Delete the task"
|
225 |
-
description="Are you sure to delete this task?"
|
226 |
-
onConfirm={(e: any) => {
|
227 |
-
e.stopPropagation();
|
228 |
-
e.nativeEvent.stopImmediatePropagation();
|
229 |
-
console.log(confirm);
|
230 |
-
confirm(item.chunk_id);
|
231 |
-
}}
|
232 |
-
okText="Yes"
|
233 |
-
cancelText="No"
|
234 |
-
>
|
235 |
-
<DeleteOutlined
|
236 |
-
onClick={(e) => {
|
237 |
-
e.stopPropagation();
|
238 |
-
e.nativeEvent.stopImmediatePropagation();
|
239 |
-
}}
|
240 |
-
/>
|
241 |
-
</Popconfirm>
|
242 |
-
</span>
|
243 |
-
</div>
|
244 |
-
</div>
|
245 |
-
</Card>
|
246 |
-
</Col>
|
247 |
-
);
|
248 |
-
})}
|
249 |
-
</Row>
|
250 |
-
</Spin>
|
251 |
-
</div>
|
252 |
-
<div className={styles.pageFooter}>
|
253 |
-
<Pagination
|
254 |
-
responsive
|
255 |
-
showLessItems
|
256 |
-
showQuickJumper
|
257 |
-
showSizeChanger
|
258 |
-
onChange={onShowSizeChange}
|
259 |
-
defaultPageSize={30}
|
260 |
-
pageSizeOptions={[30, 60, 90]}
|
261 |
-
defaultCurrent={pagination.page}
|
262 |
-
total={total}
|
263 |
-
/>
|
264 |
-
</div>
|
265 |
-
</div>
|
266 |
-
</div>
|
267 |
-
<CreateModal
|
268 |
-
isShowCreateModal={isShowCreateModal}
|
269 |
-
chunk_id={chunk_id}
|
270 |
-
doc_id={doc_id}
|
271 |
-
/>
|
272 |
-
</>
|
273 |
-
);
|
274 |
-
};
|
275 |
-
|
276 |
-
export default KnowledgeSearching;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
web/src/pages/add-knowledge/components/knowledge-search/model.ts
DELETED
@@ -1,160 +0,0 @@
|
|
1 |
-
import kbService from '@/services/kbService';
|
2 |
-
import omit from 'lodash/omit';
|
3 |
-
import { DvaModel } from 'umi';
|
4 |
-
|
5 |
-
export interface KSearchModelState {
|
6 |
-
loading: boolean;
|
7 |
-
data: any[];
|
8 |
-
total: number;
|
9 |
-
isShowCreateModal: boolean;
|
10 |
-
chunk_id: string;
|
11 |
-
chunkInfo: any;
|
12 |
-
d_list: any[];
|
13 |
-
question: string;
|
14 |
-
doc_ids: any[];
|
15 |
-
pagination: any;
|
16 |
-
doc_id: string;
|
17 |
-
}
|
18 |
-
|
19 |
-
const model: DvaModel<KSearchModelState> = {
|
20 |
-
namespace: 'kSearchModel',
|
21 |
-
state: {
|
22 |
-
loading: false,
|
23 |
-
data: [],
|
24 |
-
total: 0,
|
25 |
-
isShowCreateModal: false,
|
26 |
-
chunk_id: '',
|
27 |
-
chunkInfo: {},
|
28 |
-
d_list: [],
|
29 |
-
question: '',
|
30 |
-
doc_ids: [],
|
31 |
-
pagination: { page: 1, size: 30 },
|
32 |
-
doc_id: '',
|
33 |
-
},
|
34 |
-
reducers: {
|
35 |
-
updateState(state, { payload }) {
|
36 |
-
return {
|
37 |
-
...state,
|
38 |
-
...payload,
|
39 |
-
};
|
40 |
-
},
|
41 |
-
},
|
42 |
-
subscriptions: {
|
43 |
-
setup({ dispatch, history }) {
|
44 |
-
history.listen((location) => {
|
45 |
-
console.log(location);
|
46 |
-
});
|
47 |
-
},
|
48 |
-
},
|
49 |
-
effects: {
|
50 |
-
*getKfList({ payload = {} }, { call, put }) {
|
51 |
-
const { data, response } = yield call(
|
52 |
-
kbService.get_document_list,
|
53 |
-
payload,
|
54 |
-
);
|
55 |
-
|
56 |
-
const { retcode, data: res, retmsg } = data;
|
57 |
-
if (retcode === 0) {
|
58 |
-
yield put({
|
59 |
-
type: 'updateState',
|
60 |
-
payload: {
|
61 |
-
d_list: res,
|
62 |
-
},
|
63 |
-
});
|
64 |
-
}
|
65 |
-
},
|
66 |
-
*chunk_list({ payload = {} }, { call, put, select }) {
|
67 |
-
const { question, doc_ids, pagination }: KSearchModelState = yield select(
|
68 |
-
(state: any) => state.kSearchModel,
|
69 |
-
);
|
70 |
-
const { data } = yield call(kbService.retrieval_test, {
|
71 |
-
...payload,
|
72 |
-
...pagination,
|
73 |
-
question,
|
74 |
-
doc_ids,
|
75 |
-
similarity_threshold: 0.1,
|
76 |
-
});
|
77 |
-
const { retcode, data: res, retmsg } = data;
|
78 |
-
if (retcode === 0) {
|
79 |
-
yield put({
|
80 |
-
type: 'updateState',
|
81 |
-
payload: {
|
82 |
-
data: res.chunks,
|
83 |
-
total: res.total,
|
84 |
-
},
|
85 |
-
});
|
86 |
-
}
|
87 |
-
},
|
88 |
-
*switch_chunk({ payload = {} }, { call, put }) {
|
89 |
-
const { data } = yield call(
|
90 |
-
kbService.switch_chunk,
|
91 |
-
omit(payload, ['kb_id']),
|
92 |
-
);
|
93 |
-
const { retcode } = data;
|
94 |
-
if (retcode === 0) {
|
95 |
-
yield put({
|
96 |
-
type: 'chunk_list',
|
97 |
-
payload: {
|
98 |
-
kb_id: payload.kb_id,
|
99 |
-
},
|
100 |
-
});
|
101 |
-
}
|
102 |
-
},
|
103 |
-
*rm_chunk({ payload = {} }, { call, put }) {
|
104 |
-
const { data } = yield call(kbService.rm_chunk, {
|
105 |
-
chunk_ids: payload.chunk_ids,
|
106 |
-
});
|
107 |
-
const { retcode, data: res, retmsg } = data;
|
108 |
-
if (retcode === 0) {
|
109 |
-
// TODO: Can be extracted
|
110 |
-
yield put({
|
111 |
-
type: 'chunk_list',
|
112 |
-
payload: {
|
113 |
-
kb_id: payload.kb_id,
|
114 |
-
},
|
115 |
-
});
|
116 |
-
}
|
117 |
-
},
|
118 |
-
*get_chunk({ payload = {} }, { call, put }) {
|
119 |
-
const { data, response } = yield call(kbService.get_chunk, payload);
|
120 |
-
const { retcode, data: res, retmsg } = data;
|
121 |
-
if (retcode === 0) {
|
122 |
-
yield put({
|
123 |
-
type: 'updateState',
|
124 |
-
payload: {
|
125 |
-
chunkInfo: res,
|
126 |
-
},
|
127 |
-
});
|
128 |
-
}
|
129 |
-
},
|
130 |
-
*create_hunk({ payload = {} }, { call, put }) {
|
131 |
-
yield put({
|
132 |
-
type: 'updateState',
|
133 |
-
payload: {
|
134 |
-
loading: true,
|
135 |
-
},
|
136 |
-
});
|
137 |
-
let service = kbService.create_chunk;
|
138 |
-
if (payload.chunk_id) {
|
139 |
-
service = kbService.set_chunk;
|
140 |
-
}
|
141 |
-
const { data } = yield call(service, payload);
|
142 |
-
const { retcode } = data;
|
143 |
-
yield put({
|
144 |
-
type: 'updateState',
|
145 |
-
payload: {
|
146 |
-
loading: false,
|
147 |
-
},
|
148 |
-
});
|
149 |
-
if (retcode === 0) {
|
150 |
-
yield put({
|
151 |
-
type: 'updateState',
|
152 |
-
payload: {
|
153 |
-
isShowCreateModal: false,
|
154 |
-
},
|
155 |
-
});
|
156 |
-
}
|
157 |
-
},
|
158 |
-
},
|
159 |
-
};
|
160 |
-
export default model;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx
ADDED
@@ -0,0 +1,217 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
useFetchKnowledgeBaseConfiguration,
|
3 |
+
useFetchParserList,
|
4 |
+
useKnowledgeBaseId,
|
5 |
+
useSelectParserList,
|
6 |
+
} from '@/hooks/knowledgeHook';
|
7 |
+
import {
|
8 |
+
Button,
|
9 |
+
Divider,
|
10 |
+
Form,
|
11 |
+
Input,
|
12 |
+
Radio,
|
13 |
+
Select,
|
14 |
+
Space,
|
15 |
+
Typography,
|
16 |
+
Upload,
|
17 |
+
UploadFile,
|
18 |
+
} from 'antd';
|
19 |
+
import pick from 'lodash/pick';
|
20 |
+
import { useCallback, useEffect, useMemo } from 'react';
|
21 |
+
import { useDispatch, useSelector } from 'umi';
|
22 |
+
|
23 |
+
import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
|
24 |
+
import { IKnowledge } from '@/interfaces/database/knowledge';
|
25 |
+
import { IThirdOAIModelCollection } from '@/interfaces/database/llm';
|
26 |
+
import { PlusOutlined } from '@ant-design/icons';
|
27 |
+
import styles from './index.less';
|
28 |
+
|
29 |
+
const { Title } = Typography;
|
30 |
+
const { Option } = Select;
|
31 |
+
|
32 |
+
const Configuration = () => {
|
33 |
+
const [form] = Form.useForm();
|
34 |
+
const dispatch = useDispatch();
|
35 |
+
const knowledgeBaseId = useKnowledgeBaseId();
|
36 |
+
const loading = useOneNamespaceEffectsLoading('kSModel', ['updateKb']);
|
37 |
+
|
38 |
+
const llmInfo: IThirdOAIModelCollection = useSelector(
|
39 |
+
(state: any) => state.settingModel.llmInfo,
|
40 |
+
);
|
41 |
+
const knowledgeDetails: IKnowledge = useSelector(
|
42 |
+
(state: any) => state.kSModel.knowledgeDetails,
|
43 |
+
);
|
44 |
+
|
45 |
+
const normFile = (e: any) => {
|
46 |
+
if (Array.isArray(e)) {
|
47 |
+
return e;
|
48 |
+
}
|
49 |
+
return e?.fileList;
|
50 |
+
};
|
51 |
+
|
52 |
+
const parserList = useSelectParserList();
|
53 |
+
|
54 |
+
const embeddingModelOptions = useMemo(() => {
|
55 |
+
return Object.entries(llmInfo).map(([key, value]) => {
|
56 |
+
return {
|
57 |
+
label: key,
|
58 |
+
options: value.map((x) => ({
|
59 |
+
label: x.llm_name,
|
60 |
+
value: x.llm_name,
|
61 |
+
})),
|
62 |
+
};
|
63 |
+
});
|
64 |
+
}, [llmInfo]);
|
65 |
+
|
66 |
+
const onFinish = async (values: any) => {
|
67 |
+
console.info(values);
|
68 |
+
const fileList = values.avatar;
|
69 |
+
let avatar;
|
70 |
+
|
71 |
+
if (Array.isArray(fileList)) {
|
72 |
+
avatar = fileList[0].thumbUrl;
|
73 |
+
}
|
74 |
+
|
75 |
+
dispatch({
|
76 |
+
type: 'kSModel/updateKb',
|
77 |
+
payload: {
|
78 |
+
...values,
|
79 |
+
avatar,
|
80 |
+
kb_id: knowledgeBaseId,
|
81 |
+
},
|
82 |
+
});
|
83 |
+
};
|
84 |
+
|
85 |
+
const onFinishFailed = (errorInfo: any) => {
|
86 |
+
console.log('Failed:', errorInfo);
|
87 |
+
};
|
88 |
+
|
89 |
+
const fetchLlmList = useCallback(() => {
|
90 |
+
dispatch({
|
91 |
+
type: 'settingModel/llm_list',
|
92 |
+
payload: { model_type: 'embedding' },
|
93 |
+
});
|
94 |
+
}, [dispatch]);
|
95 |
+
|
96 |
+
useEffect(() => {
|
97 |
+
const avatar = knowledgeDetails.avatar;
|
98 |
+
let fileList: UploadFile[] = [];
|
99 |
+
|
100 |
+
if (avatar) {
|
101 |
+
fileList = [{ uid: '1', name: 'file', thumbUrl: avatar, status: 'done' }];
|
102 |
+
}
|
103 |
+
form.setFieldsValue({
|
104 |
+
...pick(knowledgeDetails, [
|
105 |
+
'description',
|
106 |
+
'name',
|
107 |
+
'permission',
|
108 |
+
'embd_id',
|
109 |
+
'parser_id',
|
110 |
+
]),
|
111 |
+
avatar: fileList,
|
112 |
+
});
|
113 |
+
}, [form, knowledgeDetails]);
|
114 |
+
|
115 |
+
useFetchParserList();
|
116 |
+
useFetchKnowledgeBaseConfiguration();
|
117 |
+
|
118 |
+
useEffect(() => {
|
119 |
+
fetchLlmList();
|
120 |
+
}, [fetchLlmList]);
|
121 |
+
|
122 |
+
return (
|
123 |
+
<div className={styles.configurationWrapper}>
|
124 |
+
<Title level={5}>Configuration</Title>
|
125 |
+
<p>Update your knowledge base details especially parsing method here.</p>
|
126 |
+
<Divider></Divider>
|
127 |
+
<Form
|
128 |
+
form={form}
|
129 |
+
name="validateOnly"
|
130 |
+
layout="vertical"
|
131 |
+
autoComplete="off"
|
132 |
+
onFinish={onFinish}
|
133 |
+
onFinishFailed={onFinishFailed}
|
134 |
+
>
|
135 |
+
<Form.Item
|
136 |
+
name="name"
|
137 |
+
label="Knowledge base name"
|
138 |
+
rules={[{ required: true }]}
|
139 |
+
>
|
140 |
+
<Input />
|
141 |
+
</Form.Item>
|
142 |
+
<Form.Item
|
143 |
+
name="avatar"
|
144 |
+
label="Knowledge base photo"
|
145 |
+
valuePropName="fileList"
|
146 |
+
getValueFromEvent={normFile}
|
147 |
+
>
|
148 |
+
<Upload
|
149 |
+
listType="picture-card"
|
150 |
+
maxCount={1}
|
151 |
+
showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }}
|
152 |
+
>
|
153 |
+
<button style={{ border: 0, background: 'none' }} type="button">
|
154 |
+
<PlusOutlined />
|
155 |
+
<div style={{ marginTop: 8 }}>Upload</div>
|
156 |
+
</button>
|
157 |
+
</Upload>
|
158 |
+
</Form.Item>
|
159 |
+
<Form.Item name="description" label="Knowledge base bio">
|
160 |
+
<Input />
|
161 |
+
</Form.Item>
|
162 |
+
<Form.Item
|
163 |
+
name="permission"
|
164 |
+
label="Permissions"
|
165 |
+
rules={[{ required: true }]}
|
166 |
+
>
|
167 |
+
<Radio.Group>
|
168 |
+
<Radio value="me">Only me</Radio>
|
169 |
+
<Radio value="team">Team</Radio>
|
170 |
+
</Radio.Group>
|
171 |
+
</Form.Item>
|
172 |
+
<Form.Item
|
173 |
+
name="embd_id"
|
174 |
+
label="Embedding Model"
|
175 |
+
rules={[{ required: true }]}
|
176 |
+
>
|
177 |
+
<Select
|
178 |
+
placeholder="Please select a country"
|
179 |
+
options={embeddingModelOptions}
|
180 |
+
></Select>
|
181 |
+
</Form.Item>
|
182 |
+
<Form.Item
|
183 |
+
name="parser_id"
|
184 |
+
label="Knowledge base category"
|
185 |
+
rules={[{ required: true }]}
|
186 |
+
>
|
187 |
+
<Select placeholder="Please select a country">
|
188 |
+
{parserList.map((x) => (
|
189 |
+
<Option value={x.value} key={x.value}>
|
190 |
+
{x.label}
|
191 |
+
</Option>
|
192 |
+
))}
|
193 |
+
</Select>
|
194 |
+
</Form.Item>
|
195 |
+
<Form.Item>
|
196 |
+
<div className={styles.buttonWrapper}>
|
197 |
+
<Space>
|
198 |
+
<Button htmlType="reset" size={'middle'}>
|
199 |
+
Cancel
|
200 |
+
</Button>
|
201 |
+
<Button
|
202 |
+
htmlType="submit"
|
203 |
+
type="primary"
|
204 |
+
size={'middle'}
|
205 |
+
loading={loading}
|
206 |
+
>
|
207 |
+
Save
|
208 |
+
</Button>
|
209 |
+
</Space>
|
210 |
+
</div>
|
211 |
+
</Form.Item>
|
212 |
+
</Form>
|
213 |
+
</div>
|
214 |
+
);
|
215 |
+
};
|
216 |
+
|
217 |
+
export default Configuration;
|
web/src/pages/add-knowledge/components/knowledge-setting/index.less
CHANGED
@@ -1,24 +1,30 @@
|
|
1 |
.tags {
|
2 |
-
|
3 |
}
|
4 |
|
5 |
.preset {
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
|
13 |
-
|
14 |
-
|
|
|
15 |
|
16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
}
|
|
|
1 |
.tags {
|
2 |
+
margin-bottom: 24px;
|
3 |
}
|
4 |
|
5 |
.preset {
|
6 |
+
display: flex;
|
7 |
+
height: 80px;
|
8 |
+
background-color: rgba(0, 0, 0, 0.1);
|
9 |
+
border-radius: 5px;
|
10 |
+
padding: 5px;
|
11 |
+
margin-bottom: 24px;
|
12 |
|
13 |
+
.left {
|
14 |
+
flex: 1;
|
15 |
+
}
|
16 |
|
17 |
+
.right {
|
18 |
+
width: 100px;
|
19 |
+
border-left: 1px solid rgba(0, 0, 0, 0.4);
|
20 |
+
margin: 10px 0px;
|
21 |
+
padding: 5px;
|
22 |
+
}
|
23 |
+
}
|
24 |
|
25 |
+
.configurationWrapper {
|
26 |
+
padding: 0 52px;
|
27 |
+
.buttonWrapper {
|
28 |
+
text-align: right;
|
29 |
+
}
|
30 |
+
}
|
|
web/src/pages/add-knowledge/components/knowledge-setting/index.tsx
CHANGED
@@ -3,6 +3,8 @@ import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
|
|
3 |
import { Button, Form, Input, Radio, Select, Space, Tag } from 'antd';
|
4 |
import { useCallback, useEffect, useState } from 'react';
|
5 |
import { useDispatch, useNavigate, useSelector } from 'umi';
|
|
|
|
|
6 |
import styles from './index.less';
|
7 |
|
8 |
const { CheckableTag } = Tag;
|
@@ -12,7 +14,6 @@ const layout = {
|
|
12 |
labelAlign: 'left' as const,
|
13 |
};
|
14 |
const { Option } = Select;
|
15 |
-
/* eslint-disable no-template-curly-in-string */
|
16 |
|
17 |
const KnowledgeSetting = () => {
|
18 |
const dispatch = useDispatch();
|
@@ -44,7 +45,7 @@ const KnowledgeSetting = () => {
|
|
44 |
setSelectedTag(data.data.parser_id);
|
45 |
}
|
46 |
}
|
47 |
-
}, [knowledgeBaseId]);
|
48 |
|
49 |
const onFinish = async () => {
|
50 |
try {
|
@@ -68,10 +69,11 @@ const KnowledgeSetting = () => {
|
|
68 |
parser_id: selectedTag,
|
69 |
},
|
70 |
});
|
71 |
-
retcode === 0
|
72 |
navigate(
|
73 |
`/knowledge/${KnowledgeRouteKey.Dataset}?id=${knowledgeBaseId}`,
|
74 |
);
|
|
|
75 |
}
|
76 |
} catch (error) {
|
77 |
console.warn(error);
|
@@ -158,4 +160,6 @@ const KnowledgeSetting = () => {
|
|
158 |
);
|
159 |
};
|
160 |
|
161 |
-
export default KnowledgeSetting;
|
|
|
|
|
|
3 |
import { Button, Form, Input, Radio, Select, Space, Tag } from 'antd';
|
4 |
import { useCallback, useEffect, useState } from 'react';
|
5 |
import { useDispatch, useNavigate, useSelector } from 'umi';
|
6 |
+
import Configuration from './configuration';
|
7 |
+
|
8 |
import styles from './index.less';
|
9 |
|
10 |
const { CheckableTag } = Tag;
|
|
|
14 |
labelAlign: 'left' as const,
|
15 |
};
|
16 |
const { Option } = Select;
|
|
|
17 |
|
18 |
const KnowledgeSetting = () => {
|
19 |
const dispatch = useDispatch();
|
|
|
45 |
setSelectedTag(data.data.parser_id);
|
46 |
}
|
47 |
}
|
48 |
+
}, [knowledgeBaseId, dispatch, form]);
|
49 |
|
50 |
const onFinish = async () => {
|
51 |
try {
|
|
|
69 |
parser_id: selectedTag,
|
70 |
},
|
71 |
});
|
72 |
+
if (retcode === 0) {
|
73 |
navigate(
|
74 |
`/knowledge/${KnowledgeRouteKey.Dataset}?id=${knowledgeBaseId}`,
|
75 |
);
|
76 |
+
}
|
77 |
}
|
78 |
} catch (error) {
|
79 |
console.warn(error);
|
|
|
160 |
);
|
161 |
};
|
162 |
|
163 |
+
// export default KnowledgeSetting;
|
164 |
+
|
165 |
+
export default Configuration;
|
web/src/pages/add-knowledge/components/knowledge-setting/model.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
|
|
1 |
import kbService from '@/services/kbService';
|
2 |
import { message } from 'antd';
|
3 |
import { DvaModel } from 'umi';
|
@@ -6,6 +7,7 @@ export interface KSModelState {
|
|
6 |
isShowPSwModal: boolean;
|
7 |
isShowTntModal: boolean;
|
8 |
tenantIfo: any;
|
|
|
9 |
}
|
10 |
|
11 |
const model: DvaModel<KSModelState> = {
|
@@ -14,6 +16,7 @@ const model: DvaModel<KSModelState> = {
|
|
14 |
isShowPSwModal: false,
|
15 |
isShowTntModal: false,
|
16 |
tenantIfo: {},
|
|
|
17 |
},
|
18 |
reducers: {
|
19 |
updateState(state, { payload }) {
|
@@ -22,31 +25,32 @@ const model: DvaModel<KSModelState> = {
|
|
22 |
...payload,
|
23 |
};
|
24 |
},
|
25 |
-
|
26 |
-
|
27 |
-
setup({ dispatch, history }) {
|
28 |
-
history.listen((location) => {});
|
29 |
},
|
30 |
},
|
31 |
effects: {
|
32 |
-
*createKb({ payload = {} }, { call
|
33 |
const { data } = yield call(kbService.createKb, payload);
|
34 |
const { retcode } = data;
|
35 |
if (retcode === 0) {
|
36 |
-
message.success('
|
37 |
}
|
38 |
return data;
|
39 |
},
|
40 |
*updateKb({ payload = {} }, { call, put }) {
|
41 |
const { data } = yield call(kbService.updateKb, payload);
|
42 |
-
const { retcode
|
43 |
if (retcode === 0) {
|
44 |
-
|
|
|
45 |
}
|
46 |
},
|
47 |
*getKbDetail({ payload = {} }, { call, put }) {
|
48 |
const { data } = yield call(kbService.get_kb_detail, payload);
|
49 |
-
|
|
|
|
|
50 |
return data;
|
51 |
},
|
52 |
},
|
|
|
1 |
+
import { IKnowledge } from '@/interfaces/database/knowledge';
|
2 |
import kbService from '@/services/kbService';
|
3 |
import { message } from 'antd';
|
4 |
import { DvaModel } from 'umi';
|
|
|
7 |
isShowPSwModal: boolean;
|
8 |
isShowTntModal: boolean;
|
9 |
tenantIfo: any;
|
10 |
+
knowledgeDetails: IKnowledge;
|
11 |
}
|
12 |
|
13 |
const model: DvaModel<KSModelState> = {
|
|
|
16 |
isShowPSwModal: false,
|
17 |
isShowTntModal: false,
|
18 |
tenantIfo: {},
|
19 |
+
knowledgeDetails: {} as any,
|
20 |
},
|
21 |
reducers: {
|
22 |
updateState(state, { payload }) {
|
|
|
25 |
...payload,
|
26 |
};
|
27 |
},
|
28 |
+
setKnowledgeDetails(state, { payload }) {
|
29 |
+
return { ...state, knowledgeDetails: payload };
|
|
|
|
|
30 |
},
|
31 |
},
|
32 |
effects: {
|
33 |
+
*createKb({ payload = {} }, { call }) {
|
34 |
const { data } = yield call(kbService.createKb, payload);
|
35 |
const { retcode } = data;
|
36 |
if (retcode === 0) {
|
37 |
+
message.success('Created successfully!');
|
38 |
}
|
39 |
return data;
|
40 |
},
|
41 |
*updateKb({ payload = {} }, { call, put }) {
|
42 |
const { data } = yield call(kbService.updateKb, payload);
|
43 |
+
const { retcode } = data;
|
44 |
if (retcode === 0) {
|
45 |
+
yield put({ type: 'getKbDetail', payload: { kb_id: payload.kb_id } });
|
46 |
+
message.success('Updated successfully!');
|
47 |
}
|
48 |
},
|
49 |
*getKbDetail({ payload = {} }, { call, put }) {
|
50 |
const { data } = yield call(kbService.get_kb_detail, payload);
|
51 |
+
if (data.retcode === 0) {
|
52 |
+
yield put({ type: 'setKnowledgeDetails', payload: data.data });
|
53 |
+
}
|
54 |
return data;
|
55 |
},
|
56 |
},
|
web/src/pages/add-knowledge/components/knowledge-sidebar/index.tsx
CHANGED
@@ -1,9 +1,10 @@
|
|
1 |
-
import { ReactComponent as
|
2 |
import { ReactComponent as DatasetIcon } from '@/assets/svg/knowledge-dataset.svg';
|
3 |
import { ReactComponent as TestingIcon } from '@/assets/svg/knowledge-testing.svg';
|
|
|
4 |
import { useSecondPathName } from '@/hooks/routeHook';
|
|
|
5 |
import { getWidth } from '@/utils';
|
6 |
-
import { AntDesignOutlined } from '@ant-design/icons';
|
7 |
import { Avatar, Menu, MenuProps, Space } from 'antd';
|
8 |
import classNames from 'classnames';
|
9 |
import { useCallback, useEffect, useMemo, useState } from 'react';
|
@@ -16,6 +17,9 @@ const KnowledgeSidebar = () => {
|
|
16 |
const { id } = kAModel;
|
17 |
let navigate = useNavigate();
|
18 |
const activeKey = useSecondPathName();
|
|
|
|
|
|
|
19 |
|
20 |
const [windowWidth, setWindowWidth] = useState(getWidth());
|
21 |
const [collapsed, setCollapsed] = useState(false);
|
@@ -62,12 +66,7 @@ const KnowledgeSidebar = () => {
|
|
62 |
getItem(
|
63 |
routeMap[KnowledgeRouteKey.Configuration],
|
64 |
KnowledgeRouteKey.Configuration,
|
65 |
-
<
|
66 |
-
),
|
67 |
-
getItem(
|
68 |
-
routeMap[KnowledgeRouteKey.TempTesting],
|
69 |
-
KnowledgeRouteKey.TempTesting,
|
70 |
-
<TestingIcon />,
|
71 |
),
|
72 |
];
|
73 |
}, [getItem]);
|
@@ -93,16 +92,17 @@ const KnowledgeSidebar = () => {
|
|
93 |
};
|
94 |
}, []);
|
95 |
|
|
|
|
|
96 |
return (
|
97 |
<div className={styles.sidebarWrapper}>
|
98 |
<div className={styles.sidebarTop}>
|
99 |
<Space size={8} direction="vertical">
|
100 |
-
<Avatar size={64}
|
101 |
-
<div className={styles.knowledgeTitle}>
|
102 |
</Space>
|
103 |
<p className={styles.knowledgeDescription}>
|
104 |
-
|
105 |
-
computing and data storage.
|
106 |
</p>
|
107 |
</div>
|
108 |
<div className={styles.divider}></div>
|
|
|
1 |
+
import { ReactComponent as ConfigurationIcon } from '@/assets/svg/knowledge-configration.svg';
|
2 |
import { ReactComponent as DatasetIcon } from '@/assets/svg/knowledge-dataset.svg';
|
3 |
import { ReactComponent as TestingIcon } from '@/assets/svg/knowledge-testing.svg';
|
4 |
+
import { useFetchKnowledgeBaseConfiguration } from '@/hooks/knowledgeHook';
|
5 |
import { useSecondPathName } from '@/hooks/routeHook';
|
6 |
+
import { IKnowledge } from '@/interfaces/database/knowledge';
|
7 |
import { getWidth } from '@/utils';
|
|
|
8 |
import { Avatar, Menu, MenuProps, Space } from 'antd';
|
9 |
import classNames from 'classnames';
|
10 |
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
|
17 |
const { id } = kAModel;
|
18 |
let navigate = useNavigate();
|
19 |
const activeKey = useSecondPathName();
|
20 |
+
const knowledgeDetails: IKnowledge = useSelector(
|
21 |
+
(state: any) => state.kSModel.knowledgeDetails,
|
22 |
+
);
|
23 |
|
24 |
const [windowWidth, setWindowWidth] = useState(getWidth());
|
25 |
const [collapsed, setCollapsed] = useState(false);
|
|
|
66 |
getItem(
|
67 |
routeMap[KnowledgeRouteKey.Configuration],
|
68 |
KnowledgeRouteKey.Configuration,
|
69 |
+
<ConfigurationIcon />,
|
|
|
|
|
|
|
|
|
|
|
70 |
),
|
71 |
];
|
72 |
}, [getItem]);
|
|
|
92 |
};
|
93 |
}, []);
|
94 |
|
95 |
+
useFetchKnowledgeBaseConfiguration();
|
96 |
+
|
97 |
return (
|
98 |
<div className={styles.sidebarWrapper}>
|
99 |
<div className={styles.sidebarTop}>
|
100 |
<Space size={8} direction="vertical">
|
101 |
+
<Avatar size={64} src={knowledgeDetails.avatar} />
|
102 |
+
<div className={styles.knowledgeTitle}>{knowledgeDetails.name}</div>
|
103 |
</Space>
|
104 |
<p className={styles.knowledgeDescription}>
|
105 |
+
{knowledgeDetails.description}
|
|
|
106 |
</p>
|
107 |
</div>
|
108 |
<div className={styles.divider}></div>
|
web/src/pages/setting/model.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
import { ITenantInfo } from '@/interfaces/database/knowledge';
|
|
|
2 |
import userService from '@/services/userService';
|
3 |
import authorizationUtil from '@/utils/authorizationUtil';
|
4 |
import { message } from 'antd';
|
@@ -12,7 +13,7 @@ export interface SettingModelState {
|
|
12 |
isShowSSModal: boolean;
|
13 |
llm_factory: string;
|
14 |
tenantIfo: Nullable<ITenantInfo>;
|
15 |
-
llmInfo:
|
16 |
myLlm: any[];
|
17 |
factoriesList: any[];
|
18 |
}
|
@@ -126,8 +127,8 @@ const model: DvaModel<SettingModelState> = {
|
|
126 |
}
|
127 |
},
|
128 |
*llm_list({ payload = {} }, { call, put }) {
|
129 |
-
const { data
|
130 |
-
const { retcode, data: res
|
131 |
if (retcode === 0) {
|
132 |
yield put({
|
133 |
type: 'updateState',
|
|
|
1 |
import { ITenantInfo } from '@/interfaces/database/knowledge';
|
2 |
+
import { IThirdOAIModelCollection as IThirdAiModelCollection } from '@/interfaces/database/llm';
|
3 |
import userService from '@/services/userService';
|
4 |
import authorizationUtil from '@/utils/authorizationUtil';
|
5 |
import { message } from 'antd';
|
|
|
13 |
isShowSSModal: boolean;
|
14 |
llm_factory: string;
|
15 |
tenantIfo: Nullable<ITenantInfo>;
|
16 |
+
llmInfo: IThirdAiModelCollection;
|
17 |
myLlm: any[];
|
18 |
factoriesList: any[];
|
19 |
}
|
|
|
127 |
}
|
128 |
},
|
129 |
*llm_list({ payload = {} }, { call, put }) {
|
130 |
+
const { data } = yield call(userService.llm_list, payload);
|
131 |
+
const { retcode, data: res } = data;
|
132 |
if (retcode === 0) {
|
133 |
yield put({
|
134 |
type: 'updateState',
|
web/src/routes.ts
CHANGED
@@ -44,10 +44,6 @@ const routes = [
|
|
44 |
},
|
45 |
{
|
46 |
path: '/knowledge/testing',
|
47 |
-
component: '@/pages/add-knowledge/components/knowledge-search',
|
48 |
-
},
|
49 |
-
{
|
50 |
-
path: '/knowledge/tempTesting',
|
51 |
component: '@/pages/add-knowledge/components/knowledge-testing',
|
52 |
},
|
53 |
],
|
|
|
44 |
},
|
45 |
{
|
46 |
path: '/knowledge/testing',
|
|
|
|
|
|
|
|
|
47 |
component: '@/pages/add-knowledge/components/knowledge-testing',
|
48 |
},
|
49 |
],
|
web/src/utils/fileUtil.ts
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export const transformFile2Base64 = (val: any): Promise<any> => {
|
2 |
+
return new Promise((resolve, reject) => {
|
3 |
+
const reader = new FileReader();
|
4 |
+
reader.readAsDataURL(val);
|
5 |
+
reader.onload = (): void => {
|
6 |
+
resolve(reader.result);
|
7 |
+
};
|
8 |
+
reader.onerror = reject;
|
9 |
+
});
|
10 |
+
};
|
11 |
+
|
12 |
+
export const transformBase64ToFile = (
|
13 |
+
dataUrl: string,
|
14 |
+
filename: string = 'file',
|
15 |
+
) => {
|
16 |
+
let arr = dataUrl.split(','),
|
17 |
+
bstr = atob(arr[1]),
|
18 |
+
n = bstr.length,
|
19 |
+
u8arr = new Uint8Array(n);
|
20 |
+
|
21 |
+
const mime = arr[0].match(/:(.*?);/);
|
22 |
+
const mimeType = mime ? mime[1] : 'image/png';
|
23 |
+
|
24 |
+
while (n--) {
|
25 |
+
u8arr[n] = bstr.charCodeAt(n);
|
26 |
+
}
|
27 |
+
return new File([u8arr], filename, { type: mimeType });
|
28 |
+
};
|