mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
feat: remove KnowledgeSearching and add knowledge configuration page and add a run button to the document (#64)
* feat: add a run button to the document * feat: add knowledge configuration page * feat: remove KnowledgeSearching
This commit is contained in:
@ -26,6 +26,7 @@
|
||||
.chunkContainer {
|
||||
height: calc(100vh - 320px);
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pageFooter {
|
||||
|
||||
@ -2,10 +2,11 @@ import { ReactComponent as SelectFilesEndIcon } from '@/assets/svg/select-files-
|
||||
import { ReactComponent as SelectFilesStartIcon } from '@/assets/svg/select-files-start.svg';
|
||||
import {
|
||||
useDeleteDocumentById,
|
||||
useFetchParserList,
|
||||
useGetDocumentDefaultParser,
|
||||
useKnowledgeBaseId,
|
||||
useSelectParserList,
|
||||
} from '@/hooks/knowledgeHook';
|
||||
import { ITenantInfo } from '@/interfaces/database/knowledge';
|
||||
import uploadService from '@/services/uploadService';
|
||||
import {
|
||||
ArrowLeftOutlined,
|
||||
@ -28,9 +29,8 @@ import {
|
||||
UploadProps,
|
||||
} from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { ReactElement, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Nullable } from 'typings';
|
||||
import { Link, useDispatch, useNavigate, useSelector } from 'umi';
|
||||
import { ReactElement, useEffect, useRef, useState } from 'react';
|
||||
import { Link, useDispatch, useNavigate } from 'umi';
|
||||
|
||||
import { KnowledgeRouteKey } from '@/constants/knowledge';
|
||||
import styles from './index.less';
|
||||
@ -45,13 +45,11 @@ const UploaderItem = ({
|
||||
file,
|
||||
actions,
|
||||
isUpload,
|
||||
parserArray,
|
||||
}: {
|
||||
isUpload: boolean;
|
||||
originNode: ReactElement;
|
||||
file: UploadFile;
|
||||
fileList: object[];
|
||||
parserArray: string[];
|
||||
actions: { download: Function; preview: Function; remove: any };
|
||||
}) => {
|
||||
const { parserConfig, defaultParserId } = useGetDocumentDefaultParser(
|
||||
@ -63,12 +61,7 @@ const UploaderItem = ({
|
||||
|
||||
const documentId = file?.response?.id;
|
||||
|
||||
const parserList = useMemo(() => {
|
||||
return parserArray.map((x) => {
|
||||
const arr = x.split(':');
|
||||
return { value: arr[0], label: arr[1] };
|
||||
});
|
||||
}, [parserArray]);
|
||||
const parserList = useSelectParserList();
|
||||
|
||||
const saveParser = (parserId: string) => {
|
||||
dispatch({
|
||||
@ -154,14 +147,10 @@ const KnowledgeUploadFile = () => {
|
||||
const knowledgeBaseId = useKnowledgeBaseId();
|
||||
const [isUpload, setIsUpload] = useState(true);
|
||||
const dispatch = useDispatch();
|
||||
const tenantIfo: Nullable<ITenantInfo> = useSelector(
|
||||
(state: any) => state.settingModel.tenantIfo,
|
||||
);
|
||||
|
||||
const navigate = useNavigate();
|
||||
const fileListRef = useRef<UploadFile[]>([]);
|
||||
|
||||
const parserArray = tenantIfo?.parser_ids.split(',') ?? [];
|
||||
|
||||
const createRequest: (props: UploadRequestOption) => void = async function ({
|
||||
file,
|
||||
onSuccess,
|
||||
@ -170,9 +159,13 @@ const KnowledgeUploadFile = () => {
|
||||
}) {
|
||||
const { data } = await uploadService.uploadFile(file, knowledgeBaseId);
|
||||
if (data.retcode === 0) {
|
||||
onSuccess && onSuccess(data.data);
|
||||
if (onSuccess) {
|
||||
onSuccess(data.data);
|
||||
}
|
||||
} else {
|
||||
onError && onError(data.data);
|
||||
if (onError) {
|
||||
onError(data.data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -188,7 +181,6 @@ const KnowledgeUploadFile = () => {
|
||||
fileList={fileList}
|
||||
originNode={originNode}
|
||||
actions={actions}
|
||||
parserArray={parserArray}
|
||||
></UploaderItem>
|
||||
);
|
||||
},
|
||||
@ -215,11 +207,7 @@ const KnowledgeUploadFile = () => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({
|
||||
type: 'settingModel/getTenantInfo',
|
||||
});
|
||||
}, []);
|
||||
useFetchParserList();
|
||||
|
||||
return (
|
||||
<div className={styles.uploadWrapper}>
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
import { KnowledgeRouteKey } from '@/constants/knowledge';
|
||||
import {
|
||||
useDeleteDocumentById,
|
||||
useKnowledgeBaseId,
|
||||
} from '@/hooks/knowledgeHook';
|
||||
import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
|
||||
import { Pagination } from '@/interfaces/common';
|
||||
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
|
||||
import { getOneNamespaceEffectsLoading } from '@/utils/storeUtil';
|
||||
@ -40,7 +37,6 @@ const KnowledgeFile = () => {
|
||||
const effects = useSelector((state: any) => state.loading.effects);
|
||||
const { data, total } = kFModel;
|
||||
const knowledgeBaseId = useKnowledgeBaseId();
|
||||
const { removeDocument } = useDeleteDocumentById();
|
||||
|
||||
const loading = getOneNamespaceEffectsLoading('kFModel', effects, [
|
||||
'getKfList',
|
||||
@ -132,9 +128,7 @@ const KnowledgeFile = () => {
|
||||
},
|
||||
});
|
||||
};
|
||||
const onRmDocument = () => {
|
||||
removeDocument(doc_id);
|
||||
};
|
||||
|
||||
const showCEFModal = () => {
|
||||
dispatch({
|
||||
type: 'kFModel/updateState',
|
||||
@ -144,15 +138,6 @@ const KnowledgeFile = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const showSegmentSetModal = () => {
|
||||
dispatch({
|
||||
type: 'kFModel/updateState',
|
||||
payload: {
|
||||
isShowSegmentSetModal: true,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const actionItems: MenuProps['items'] = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
@ -185,31 +170,6 @@ const KnowledgeFile = () => {
|
||||
},
|
||||
];
|
||||
}, []);
|
||||
const chunkItems: MenuProps['items'] = [
|
||||
{
|
||||
key: '1',
|
||||
label: (
|
||||
<div>
|
||||
<Button type="link" onClick={showSegmentSetModal}>
|
||||
{' '}
|
||||
分段设置
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: (
|
||||
<div>
|
||||
<Button type="link" onClick={onRmDocument}>
|
||||
{' '}
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
// disabled: true,
|
||||
},
|
||||
];
|
||||
|
||||
const toChunk = (id: string) => {
|
||||
navigate(
|
||||
|
||||
@ -55,33 +55,23 @@ const model: DvaModel<KFModelState> = {
|
||||
return { ...state, pagination: { ...state.pagination, ...payload } };
|
||||
},
|
||||
},
|
||||
subscriptions: {
|
||||
setup({ dispatch, history }) {
|
||||
history.listen((location) => {});
|
||||
},
|
||||
},
|
||||
effects: {
|
||||
*createKf({ payload = {} }, { call, put }) {
|
||||
const { data, response } = yield call(kbService.createKb, payload);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
*createKf({ payload = {} }, { call }) {
|
||||
const { data } = yield call(kbService.createKb, payload);
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
message.success('创建成功!');
|
||||
}
|
||||
},
|
||||
*updateKf({ payload = {} }, { call, put }) {
|
||||
const { data, response } = yield call(kbService.updateKb, payload);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
*updateKf({ payload = {} }, { call }) {
|
||||
const { data } = yield call(kbService.updateKb, payload);
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
message.success('修改成功!');
|
||||
}
|
||||
},
|
||||
*getKfDetail({ payload = {}, callback }, { call, put }) {
|
||||
const { data, response } = yield call(kbService.get_kb_detail, payload);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
if (retcode === 0) {
|
||||
// localStorage.setItem('userInfo',res.)
|
||||
callback && callback(res);
|
||||
}
|
||||
*getKfDetail({ payload = {} }, { call }) {
|
||||
const { data } = yield call(kbService.get_kb_detail, payload);
|
||||
},
|
||||
*getKfList({ payload = {} }, { call, put, select }) {
|
||||
const state: KFModelState = yield select((state: any) => state.kFModel);
|
||||
@ -119,11 +109,11 @@ const model: DvaModel<KFModelState> = {
|
||||
{ type: 'poll', delay: 5000 }, // TODO: Provide type support for this effect
|
||||
],
|
||||
*updateDocumentStatus({ payload = {} }, { call, put }) {
|
||||
const { data, response } = yield call(
|
||||
const { data } = yield call(
|
||||
kbService.document_change_status,
|
||||
pick(payload, ['doc_id', 'status']),
|
||||
);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
message.success('修改成功!');
|
||||
put({
|
||||
@ -133,10 +123,10 @@ const model: DvaModel<KFModelState> = {
|
||||
}
|
||||
},
|
||||
*document_rm({ payload = {} }, { call, put }) {
|
||||
const { data, response } = yield call(kbService.document_rm, {
|
||||
const { data } = yield call(kbService.document_rm, {
|
||||
doc_id: payload.doc_id,
|
||||
});
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
message.success('删除成功!');
|
||||
yield put({
|
||||
@ -151,7 +141,7 @@ const model: DvaModel<KFModelState> = {
|
||||
kbService.document_rename,
|
||||
omit(payload, ['kb_id']),
|
||||
);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
message.success('rename success!');
|
||||
yield put({
|
||||
@ -168,7 +158,7 @@ const model: DvaModel<KFModelState> = {
|
||||
},
|
||||
*document_create({ payload = {} }, { call, put }) {
|
||||
const { data } = yield call(kbService.document_create, payload);
|
||||
const { retcode, data: res } = data;
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
put({
|
||||
type: 'kFModel/updateState',
|
||||
@ -181,19 +171,25 @@ const model: DvaModel<KFModelState> = {
|
||||
return retcode;
|
||||
},
|
||||
*document_run({ payload = {} }, { call, put }) {
|
||||
const { data } = yield call(kbService.document_run, payload);
|
||||
const { data } = yield call(
|
||||
kbService.document_run,
|
||||
omit(payload, ['knowledgeBaseId']),
|
||||
);
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
message.success('Run successfully !');
|
||||
if (payload.knowledgeBaseId) {
|
||||
yield put({
|
||||
type: 'getKfList',
|
||||
payload: { kb_id: payload.knowledgeBaseId },
|
||||
});
|
||||
}
|
||||
message.success('Operation successfully !');
|
||||
}
|
||||
return retcode;
|
||||
},
|
||||
*document_change_parser({ payload = {} }, { call, put }) {
|
||||
const { data, response } = yield call(
|
||||
kbService.document_change_parser,
|
||||
payload,
|
||||
);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
const { data } = yield call(kbService.document_change_parser, payload);
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
put({
|
||||
type: 'updateState',
|
||||
|
||||
@ -1,3 +1,12 @@
|
||||
.popover-content {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.operationIcon {
|
||||
text-align: center;
|
||||
margin-right: 20%;
|
||||
width: 20px;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,21 @@
|
||||
import { ReactComponent as RefreshIcon } from '@/assets/svg/refresh.svg';
|
||||
import { ReactComponent as RunIcon } from '@/assets/svg/run.svg';
|
||||
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
|
||||
import { Badge, DescriptionsProps, Flex, Popover, Space, Tag } from 'antd';
|
||||
import { RunningStatus, RunningStatusMap } from '../constant';
|
||||
|
||||
import { CloseCircleOutlined } from '@ant-design/icons';
|
||||
import { useDispatch } from 'umi';
|
||||
import styles from './index.less';
|
||||
|
||||
const iconMap = {
|
||||
[RunningStatus.UNSTART]: RunIcon,
|
||||
[RunningStatus.RUNNING]: CloseCircleOutlined,
|
||||
[RunningStatus.CANCEL]: RefreshIcon,
|
||||
[RunningStatus.DONE]: RefreshIcon,
|
||||
[RunningStatus.FAIL]: RefreshIcon,
|
||||
};
|
||||
|
||||
interface IProps {
|
||||
record: IKnowledgeFile;
|
||||
}
|
||||
@ -31,7 +43,7 @@ const PopoverContent = ({ record }: IProps) => {
|
||||
<Flex vertical className={styles['popover-content']}>
|
||||
{items.map((x) => {
|
||||
return (
|
||||
<div>
|
||||
<div key={x.key}>
|
||||
<b>{x.label}:</b>
|
||||
<p>{x.children}</p>
|
||||
</div>
|
||||
@ -42,27 +54,46 @@ const PopoverContent = ({ record }: IProps) => {
|
||||
};
|
||||
|
||||
export const ParsingStatusCell = ({ record }: IProps) => {
|
||||
const dispatch = useDispatch();
|
||||
const text = record.run;
|
||||
const runningStatus = RunningStatusMap[text];
|
||||
|
||||
const isRunning = text === RunningStatus.RUNNING;
|
||||
|
||||
const OperationIcon = iconMap[text];
|
||||
|
||||
const handleOperationIconClick = () => {
|
||||
dispatch({
|
||||
type: 'kFModel/document_run',
|
||||
payload: {
|
||||
doc_ids: [record.id],
|
||||
run: isRunning ? 2 : 1,
|
||||
knowledgeBaseId: record.kb_id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Popover
|
||||
content={isRunning && <PopoverContent record={record}></PopoverContent>}
|
||||
>
|
||||
<Tag color={runningStatus.color}>
|
||||
{isRunning ? (
|
||||
<Space>
|
||||
<Badge color={runningStatus.color} />
|
||||
{runningStatus.label}
|
||||
<span>{record.progress * 100}%</span>
|
||||
</Space>
|
||||
) : (
|
||||
runningStatus.label
|
||||
)}
|
||||
</Tag>
|
||||
</Popover>
|
||||
<Flex justify={'space-between'}>
|
||||
<Popover
|
||||
content={isRunning && <PopoverContent record={record}></PopoverContent>}
|
||||
>
|
||||
<Tag color={runningStatus.color}>
|
||||
{isRunning ? (
|
||||
<Space>
|
||||
<Badge color={runningStatus.color} />
|
||||
{runningStatus.label}
|
||||
<span>{(record.progress * 100).toFixed(2)}%</span>
|
||||
</Space>
|
||||
) : (
|
||||
runningStatus.label
|
||||
)}
|
||||
</Tag>
|
||||
</Popover>
|
||||
<div onClick={handleOperationIconClick} className={styles.operationIcon}>
|
||||
<OperationIcon />
|
||||
</div>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,79 +0,0 @@
|
||||
.chunkPage {
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
height: calc(100vh - 112px);
|
||||
// flex-direction: column;
|
||||
|
||||
.filter {
|
||||
margin-right: 20px;
|
||||
display: flex;
|
||||
height: 32px;
|
||||
width: 300px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.pageContainer {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.pageContent {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding-right: 12px;
|
||||
overflow-y: auto;
|
||||
|
||||
.spin {
|
||||
min-height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.pageFooter {
|
||||
height: 32px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.context {
|
||||
flex: 1;
|
||||
// width: 207px;
|
||||
height: 88px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
height: 20px;
|
||||
|
||||
.text {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
:global {
|
||||
.ant-card-body {
|
||||
padding: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
}
|
||||
@ -1,276 +0,0 @@
|
||||
import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
|
||||
import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
|
||||
import { api_host } from '@/utils/api';
|
||||
import { DeleteOutlined, MinusSquareOutlined } from '@ant-design/icons';
|
||||
import type { PaginationProps } from 'antd';
|
||||
import {
|
||||
Card,
|
||||
Col,
|
||||
Input,
|
||||
Pagination,
|
||||
Popconfirm,
|
||||
Row,
|
||||
Select,
|
||||
Spin,
|
||||
Switch,
|
||||
} from 'antd';
|
||||
import { debounce } from 'lodash';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useDispatch, useSelector } from 'umi';
|
||||
import CreateModal from '../knowledge-chunk/components/chunk-creating-modal';
|
||||
|
||||
import styles from './index.less';
|
||||
|
||||
const KnowledgeSearching = () => {
|
||||
const dispatch = useDispatch();
|
||||
const kSearchModel = useSelector((state: any) => state.kSearchModel);
|
||||
const chunkModel = useSelector((state: any) => state.chunkModel);
|
||||
const loading = useOneNamespaceEffectsLoading('kSearchModel', [
|
||||
'chunk_list',
|
||||
'switch_chunk',
|
||||
]);
|
||||
const knowledgeBaseId = useKnowledgeBaseId();
|
||||
|
||||
const {
|
||||
data = [],
|
||||
total,
|
||||
d_list = [],
|
||||
question,
|
||||
doc_ids,
|
||||
pagination,
|
||||
} = kSearchModel;
|
||||
const { chunk_id, doc_id, isShowCreateModal } = chunkModel;
|
||||
|
||||
const getChunkList = () => {
|
||||
dispatch({
|
||||
type: 'kSearchModel/chunk_list',
|
||||
payload: {
|
||||
kb_id: knowledgeBaseId,
|
||||
},
|
||||
});
|
||||
};
|
||||
const confirm = (id: string) => {
|
||||
dispatch({
|
||||
type: 'kSearchModel/rm_chunk',
|
||||
payload: {
|
||||
chunk_ids: [id],
|
||||
kb_id: knowledgeBaseId,
|
||||
},
|
||||
});
|
||||
};
|
||||
const handleEditchunk = (item: any) => {
|
||||
const { chunk_id, doc_id } = item;
|
||||
dispatch({
|
||||
type: 'chunkModel/updateState',
|
||||
payload: {
|
||||
isShowCreateModal: true,
|
||||
chunk_id,
|
||||
doc_id,
|
||||
},
|
||||
});
|
||||
getChunkList();
|
||||
};
|
||||
const onShowSizeChange: PaginationProps['onShowSizeChange'] = (
|
||||
page,
|
||||
size,
|
||||
) => {
|
||||
dispatch({
|
||||
type: 'kSearchModel/updateState',
|
||||
payload: {
|
||||
pagination: { page, size },
|
||||
},
|
||||
});
|
||||
};
|
||||
useEffect(() => {
|
||||
dispatch({
|
||||
type: 'kSearchModel/updateState',
|
||||
payload: {
|
||||
doc_ids: [],
|
||||
question: '',
|
||||
},
|
||||
});
|
||||
dispatch({
|
||||
type: 'kSearchModel/getKfList',
|
||||
payload: {
|
||||
kb_id: knowledgeBaseId,
|
||||
},
|
||||
});
|
||||
}, []);
|
||||
const switchChunk = (item: any, available_int: boolean) => {
|
||||
const { chunk_id, doc_id } = item;
|
||||
|
||||
dispatch({
|
||||
type: 'kSearchModel/switch_chunk',
|
||||
payload: {
|
||||
chunk_ids: [chunk_id],
|
||||
doc_id,
|
||||
available_int,
|
||||
kb_id: knowledgeBaseId,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getChunkList();
|
||||
}, [doc_ids, pagination, question]);
|
||||
const debounceChange = debounce((value) => {
|
||||
dispatch({
|
||||
type: 'kSearchModel/updateState',
|
||||
payload: {
|
||||
question: value,
|
||||
},
|
||||
});
|
||||
}, 300);
|
||||
|
||||
const debounceCallback = useCallback(
|
||||
(value: string) => debounceChange(value),
|
||||
[],
|
||||
);
|
||||
const handleInputChange = (
|
||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
||||
) => {
|
||||
const value = e.target.value;
|
||||
debounceCallback(value);
|
||||
};
|
||||
const handleSelectChange = (value: any[]) => {
|
||||
dispatch({
|
||||
type: 'kSearchModel/updateState',
|
||||
payload: {
|
||||
doc_ids: value,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.chunkPage}>
|
||||
<div className={styles.filter}>
|
||||
<Select
|
||||
showSearch
|
||||
placeholder="文件列表"
|
||||
optionFilterProp="children"
|
||||
onChange={handleSelectChange}
|
||||
style={{ width: 300, marginBottom: 20 }}
|
||||
options={d_list}
|
||||
fieldNames={{ label: 'name', value: 'id' }}
|
||||
mode="multiple"
|
||||
/>
|
||||
|
||||
<Input.TextArea
|
||||
autoSize={{ minRows: 6, maxRows: 6 }}
|
||||
placeholder="搜索"
|
||||
style={{ width: 300 }}
|
||||
allowClear
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.pageContainer}>
|
||||
<div className={styles.pageContent}>
|
||||
<Spin spinning={loading} className={styles.spin} size="large">
|
||||
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24 }}>
|
||||
{data.map((item: any) => {
|
||||
return (
|
||||
<Col
|
||||
className="gutter-row"
|
||||
key={item.chunk_id}
|
||||
xs={24}
|
||||
sm={12}
|
||||
md={12}
|
||||
lg={8}
|
||||
>
|
||||
<Card
|
||||
className={styles.card}
|
||||
onClick={() => {
|
||||
handleEditchunk(item);
|
||||
}}
|
||||
>
|
||||
<img
|
||||
style={{ width: '50px' }}
|
||||
src={`${api_host}/document/image/${item.img_id}`}
|
||||
alt=""
|
||||
/>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
<span className={styles.context}>
|
||||
{item.content_ltks}
|
||||
</span>
|
||||
<span className={styles.delete}>
|
||||
<Switch
|
||||
size="small"
|
||||
defaultValue={item.doc_ids == '1'}
|
||||
onChange={(checked: boolean, e: any) => {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
switchChunk(item, checked);
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.footer}>
|
||||
<span className={styles.text}>
|
||||
<MinusSquareOutlined />
|
||||
{item.doc_num}文档
|
||||
</span>
|
||||
<span className={styles.text}>
|
||||
<MinusSquareOutlined />
|
||||
{item.chunk_num}个
|
||||
</span>
|
||||
<span className={styles.text}>
|
||||
<MinusSquareOutlined />
|
||||
{item.token_num}千字符
|
||||
</span>
|
||||
<span style={{ float: 'right' }}>
|
||||
<Popconfirm
|
||||
title="Delete the task"
|
||||
description="Are you sure to delete this task?"
|
||||
onConfirm={(e: any) => {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
console.log(confirm);
|
||||
confirm(item.chunk_id);
|
||||
}}
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
>
|
||||
<DeleteOutlined
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
}}
|
||||
/>
|
||||
</Popconfirm>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
</Spin>
|
||||
</div>
|
||||
<div className={styles.pageFooter}>
|
||||
<Pagination
|
||||
responsive
|
||||
showLessItems
|
||||
showQuickJumper
|
||||
showSizeChanger
|
||||
onChange={onShowSizeChange}
|
||||
defaultPageSize={30}
|
||||
pageSizeOptions={[30, 60, 90]}
|
||||
defaultCurrent={pagination.page}
|
||||
total={total}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<CreateModal
|
||||
isShowCreateModal={isShowCreateModal}
|
||||
chunk_id={chunk_id}
|
||||
doc_id={doc_id}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default KnowledgeSearching;
|
||||
@ -1,160 +0,0 @@
|
||||
import kbService from '@/services/kbService';
|
||||
import omit from 'lodash/omit';
|
||||
import { DvaModel } from 'umi';
|
||||
|
||||
export interface KSearchModelState {
|
||||
loading: boolean;
|
||||
data: any[];
|
||||
total: number;
|
||||
isShowCreateModal: boolean;
|
||||
chunk_id: string;
|
||||
chunkInfo: any;
|
||||
d_list: any[];
|
||||
question: string;
|
||||
doc_ids: any[];
|
||||
pagination: any;
|
||||
doc_id: string;
|
||||
}
|
||||
|
||||
const model: DvaModel<KSearchModelState> = {
|
||||
namespace: 'kSearchModel',
|
||||
state: {
|
||||
loading: false,
|
||||
data: [],
|
||||
total: 0,
|
||||
isShowCreateModal: false,
|
||||
chunk_id: '',
|
||||
chunkInfo: {},
|
||||
d_list: [],
|
||||
question: '',
|
||||
doc_ids: [],
|
||||
pagination: { page: 1, size: 30 },
|
||||
doc_id: '',
|
||||
},
|
||||
reducers: {
|
||||
updateState(state, { payload }) {
|
||||
return {
|
||||
...state,
|
||||
...payload,
|
||||
};
|
||||
},
|
||||
},
|
||||
subscriptions: {
|
||||
setup({ dispatch, history }) {
|
||||
history.listen((location) => {
|
||||
console.log(location);
|
||||
});
|
||||
},
|
||||
},
|
||||
effects: {
|
||||
*getKfList({ payload = {} }, { call, put }) {
|
||||
const { data, response } = yield call(
|
||||
kbService.get_document_list,
|
||||
payload,
|
||||
);
|
||||
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
if (retcode === 0) {
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
d_list: res,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
*chunk_list({ payload = {} }, { call, put, select }) {
|
||||
const { question, doc_ids, pagination }: KSearchModelState = yield select(
|
||||
(state: any) => state.kSearchModel,
|
||||
);
|
||||
const { data } = yield call(kbService.retrieval_test, {
|
||||
...payload,
|
||||
...pagination,
|
||||
question,
|
||||
doc_ids,
|
||||
similarity_threshold: 0.1,
|
||||
});
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
if (retcode === 0) {
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
data: res.chunks,
|
||||
total: res.total,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
*switch_chunk({ payload = {} }, { call, put }) {
|
||||
const { data } = yield call(
|
||||
kbService.switch_chunk,
|
||||
omit(payload, ['kb_id']),
|
||||
);
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
yield put({
|
||||
type: 'chunk_list',
|
||||
payload: {
|
||||
kb_id: payload.kb_id,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
*rm_chunk({ payload = {} }, { call, put }) {
|
||||
const { data } = yield call(kbService.rm_chunk, {
|
||||
chunk_ids: payload.chunk_ids,
|
||||
});
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
if (retcode === 0) {
|
||||
// TODO: Can be extracted
|
||||
yield put({
|
||||
type: 'chunk_list',
|
||||
payload: {
|
||||
kb_id: payload.kb_id,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
*get_chunk({ payload = {} }, { call, put }) {
|
||||
const { data, response } = yield call(kbService.get_chunk, payload);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
if (retcode === 0) {
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
chunkInfo: res,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
*create_hunk({ payload = {} }, { call, put }) {
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
loading: true,
|
||||
},
|
||||
});
|
||||
let service = kbService.create_chunk;
|
||||
if (payload.chunk_id) {
|
||||
service = kbService.set_chunk;
|
||||
}
|
||||
const { data } = yield call(service, payload);
|
||||
const { retcode } = data;
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
loading: false,
|
||||
},
|
||||
});
|
||||
if (retcode === 0) {
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
isShowCreateModal: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
export default model;
|
||||
@ -0,0 +1,217 @@
|
||||
import {
|
||||
useFetchKnowledgeBaseConfiguration,
|
||||
useFetchParserList,
|
||||
useKnowledgeBaseId,
|
||||
useSelectParserList,
|
||||
} from '@/hooks/knowledgeHook';
|
||||
import {
|
||||
Button,
|
||||
Divider,
|
||||
Form,
|
||||
Input,
|
||||
Radio,
|
||||
Select,
|
||||
Space,
|
||||
Typography,
|
||||
Upload,
|
||||
UploadFile,
|
||||
} from 'antd';
|
||||
import pick from 'lodash/pick';
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useDispatch, useSelector } from 'umi';
|
||||
|
||||
import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
|
||||
import { IKnowledge } from '@/interfaces/database/knowledge';
|
||||
import { IThirdOAIModelCollection } from '@/interfaces/database/llm';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import styles from './index.less';
|
||||
|
||||
const { Title } = Typography;
|
||||
const { Option } = Select;
|
||||
|
||||
const Configuration = () => {
|
||||
const [form] = Form.useForm();
|
||||
const dispatch = useDispatch();
|
||||
const knowledgeBaseId = useKnowledgeBaseId();
|
||||
const loading = useOneNamespaceEffectsLoading('kSModel', ['updateKb']);
|
||||
|
||||
const llmInfo: IThirdOAIModelCollection = useSelector(
|
||||
(state: any) => state.settingModel.llmInfo,
|
||||
);
|
||||
const knowledgeDetails: IKnowledge = useSelector(
|
||||
(state: any) => state.kSModel.knowledgeDetails,
|
||||
);
|
||||
|
||||
const normFile = (e: any) => {
|
||||
if (Array.isArray(e)) {
|
||||
return e;
|
||||
}
|
||||
return e?.fileList;
|
||||
};
|
||||
|
||||
const parserList = useSelectParserList();
|
||||
|
||||
const embeddingModelOptions = useMemo(() => {
|
||||
return Object.entries(llmInfo).map(([key, value]) => {
|
||||
return {
|
||||
label: key,
|
||||
options: value.map((x) => ({
|
||||
label: x.llm_name,
|
||||
value: x.llm_name,
|
||||
})),
|
||||
};
|
||||
});
|
||||
}, [llmInfo]);
|
||||
|
||||
const onFinish = async (values: any) => {
|
||||
console.info(values);
|
||||
const fileList = values.avatar;
|
||||
let avatar;
|
||||
|
||||
if (Array.isArray(fileList)) {
|
||||
avatar = fileList[0].thumbUrl;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: 'kSModel/updateKb',
|
||||
payload: {
|
||||
...values,
|
||||
avatar,
|
||||
kb_id: knowledgeBaseId,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const onFinishFailed = (errorInfo: any) => {
|
||||
console.log('Failed:', errorInfo);
|
||||
};
|
||||
|
||||
const fetchLlmList = useCallback(() => {
|
||||
dispatch({
|
||||
type: 'settingModel/llm_list',
|
||||
payload: { model_type: 'embedding' },
|
||||
});
|
||||
}, [dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
const avatar = knowledgeDetails.avatar;
|
||||
let fileList: UploadFile[] = [];
|
||||
|
||||
if (avatar) {
|
||||
fileList = [{ uid: '1', name: 'file', thumbUrl: avatar, status: 'done' }];
|
||||
}
|
||||
form.setFieldsValue({
|
||||
...pick(knowledgeDetails, [
|
||||
'description',
|
||||
'name',
|
||||
'permission',
|
||||
'embd_id',
|
||||
'parser_id',
|
||||
]),
|
||||
avatar: fileList,
|
||||
});
|
||||
}, [form, knowledgeDetails]);
|
||||
|
||||
useFetchParserList();
|
||||
useFetchKnowledgeBaseConfiguration();
|
||||
|
||||
useEffect(() => {
|
||||
fetchLlmList();
|
||||
}, [fetchLlmList]);
|
||||
|
||||
return (
|
||||
<div className={styles.configurationWrapper}>
|
||||
<Title level={5}>Configuration</Title>
|
||||
<p>Update your knowledge base details especially parsing method here.</p>
|
||||
<Divider></Divider>
|
||||
<Form
|
||||
form={form}
|
||||
name="validateOnly"
|
||||
layout="vertical"
|
||||
autoComplete="off"
|
||||
onFinish={onFinish}
|
||||
onFinishFailed={onFinishFailed}
|
||||
>
|
||||
<Form.Item
|
||||
name="name"
|
||||
label="Knowledge base name"
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="avatar"
|
||||
label="Knowledge base photo"
|
||||
valuePropName="fileList"
|
||||
getValueFromEvent={normFile}
|
||||
>
|
||||
<Upload
|
||||
listType="picture-card"
|
||||
maxCount={1}
|
||||
showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }}
|
||||
>
|
||||
<button style={{ border: 0, background: 'none' }} type="button">
|
||||
<PlusOutlined />
|
||||
<div style={{ marginTop: 8 }}>Upload</div>
|
||||
</button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
<Form.Item name="description" label="Knowledge base bio">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="permission"
|
||||
label="Permissions"
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Radio.Group>
|
||||
<Radio value="me">Only me</Radio>
|
||||
<Radio value="team">Team</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="embd_id"
|
||||
label="Embedding Model"
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Select
|
||||
placeholder="Please select a country"
|
||||
options={embeddingModelOptions}
|
||||
></Select>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="parser_id"
|
||||
label="Knowledge base category"
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Select placeholder="Please select a country">
|
||||
{parserList.map((x) => (
|
||||
<Option value={x.value} key={x.value}>
|
||||
{x.label}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<div className={styles.buttonWrapper}>
|
||||
<Space>
|
||||
<Button htmlType="reset" size={'middle'}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
htmlType="submit"
|
||||
type="primary"
|
||||
size={'middle'}
|
||||
loading={loading}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Configuration;
|
||||
@ -1,24 +1,30 @@
|
||||
.tags {
|
||||
margin-bottom: 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.preset {
|
||||
display: flex;
|
||||
height: 80px;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
height: 80px;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
.left {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.right {
|
||||
width: 100px;
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.4);
|
||||
margin: 10px 0px;
|
||||
padding: 5px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.left {
|
||||
flex: 1;
|
||||
|
||||
}
|
||||
|
||||
.right {
|
||||
width: 100px;
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.4);
|
||||
margin: 10px 0px;
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
.configurationWrapper {
|
||||
padding: 0 52px;
|
||||
.buttonWrapper {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,8 @@ import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
|
||||
import { Button, Form, Input, Radio, Select, Space, Tag } from 'antd';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useDispatch, useNavigate, useSelector } from 'umi';
|
||||
import Configuration from './configuration';
|
||||
|
||||
import styles from './index.less';
|
||||
|
||||
const { CheckableTag } = Tag;
|
||||
@ -12,7 +14,6 @@ const layout = {
|
||||
labelAlign: 'left' as const,
|
||||
};
|
||||
const { Option } = Select;
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
|
||||
const KnowledgeSetting = () => {
|
||||
const dispatch = useDispatch();
|
||||
@ -44,7 +45,7 @@ const KnowledgeSetting = () => {
|
||||
setSelectedTag(data.data.parser_id);
|
||||
}
|
||||
}
|
||||
}, [knowledgeBaseId]);
|
||||
}, [knowledgeBaseId, dispatch, form]);
|
||||
|
||||
const onFinish = async () => {
|
||||
try {
|
||||
@ -68,10 +69,11 @@ const KnowledgeSetting = () => {
|
||||
parser_id: selectedTag,
|
||||
},
|
||||
});
|
||||
retcode === 0 &&
|
||||
if (retcode === 0) {
|
||||
navigate(
|
||||
`/knowledge/${KnowledgeRouteKey.Dataset}?id=${knowledgeBaseId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
@ -158,4 +160,6 @@ const KnowledgeSetting = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default KnowledgeSetting;
|
||||
// export default KnowledgeSetting;
|
||||
|
||||
export default Configuration;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { IKnowledge } from '@/interfaces/database/knowledge';
|
||||
import kbService from '@/services/kbService';
|
||||
import { message } from 'antd';
|
||||
import { DvaModel } from 'umi';
|
||||
@ -6,6 +7,7 @@ export interface KSModelState {
|
||||
isShowPSwModal: boolean;
|
||||
isShowTntModal: boolean;
|
||||
tenantIfo: any;
|
||||
knowledgeDetails: IKnowledge;
|
||||
}
|
||||
|
||||
const model: DvaModel<KSModelState> = {
|
||||
@ -14,6 +16,7 @@ const model: DvaModel<KSModelState> = {
|
||||
isShowPSwModal: false,
|
||||
isShowTntModal: false,
|
||||
tenantIfo: {},
|
||||
knowledgeDetails: {} as any,
|
||||
},
|
||||
reducers: {
|
||||
updateState(state, { payload }) {
|
||||
@ -22,31 +25,32 @@ const model: DvaModel<KSModelState> = {
|
||||
...payload,
|
||||
};
|
||||
},
|
||||
},
|
||||
subscriptions: {
|
||||
setup({ dispatch, history }) {
|
||||
history.listen((location) => {});
|
||||
setKnowledgeDetails(state, { payload }) {
|
||||
return { ...state, knowledgeDetails: payload };
|
||||
},
|
||||
},
|
||||
effects: {
|
||||
*createKb({ payload = {} }, { call, put }) {
|
||||
*createKb({ payload = {} }, { call }) {
|
||||
const { data } = yield call(kbService.createKb, payload);
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
message.success('创建知识库成功!');
|
||||
message.success('Created successfully!');
|
||||
}
|
||||
return data;
|
||||
},
|
||||
*updateKb({ payload = {} }, { call, put }) {
|
||||
const { data } = yield call(kbService.updateKb, payload);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
message.success('更新知识库成功!');
|
||||
yield put({ type: 'getKbDetail', payload: { kb_id: payload.kb_id } });
|
||||
message.success('Updated successfully!');
|
||||
}
|
||||
},
|
||||
*getKbDetail({ payload = {} }, { call, put }) {
|
||||
const { data } = yield call(kbService.get_kb_detail, payload);
|
||||
|
||||
if (data.retcode === 0) {
|
||||
yield put({ type: 'setKnowledgeDetails', payload: data.data });
|
||||
}
|
||||
return data;
|
||||
},
|
||||
},
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { ReactComponent as ConfigrationIcon } from '@/assets/svg/knowledge-configration.svg';
|
||||
import { ReactComponent as ConfigurationIcon } from '@/assets/svg/knowledge-configration.svg';
|
||||
import { ReactComponent as DatasetIcon } from '@/assets/svg/knowledge-dataset.svg';
|
||||
import { ReactComponent as TestingIcon } from '@/assets/svg/knowledge-testing.svg';
|
||||
import { useFetchKnowledgeBaseConfiguration } from '@/hooks/knowledgeHook';
|
||||
import { useSecondPathName } from '@/hooks/routeHook';
|
||||
import { IKnowledge } from '@/interfaces/database/knowledge';
|
||||
import { getWidth } from '@/utils';
|
||||
import { AntDesignOutlined } from '@ant-design/icons';
|
||||
import { Avatar, Menu, MenuProps, Space } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
@ -16,6 +17,9 @@ const KnowledgeSidebar = () => {
|
||||
const { id } = kAModel;
|
||||
let navigate = useNavigate();
|
||||
const activeKey = useSecondPathName();
|
||||
const knowledgeDetails: IKnowledge = useSelector(
|
||||
(state: any) => state.kSModel.knowledgeDetails,
|
||||
);
|
||||
|
||||
const [windowWidth, setWindowWidth] = useState(getWidth());
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
@ -62,12 +66,7 @@ const KnowledgeSidebar = () => {
|
||||
getItem(
|
||||
routeMap[KnowledgeRouteKey.Configuration],
|
||||
KnowledgeRouteKey.Configuration,
|
||||
<ConfigrationIcon />,
|
||||
),
|
||||
getItem(
|
||||
routeMap[KnowledgeRouteKey.TempTesting],
|
||||
KnowledgeRouteKey.TempTesting,
|
||||
<TestingIcon />,
|
||||
<ConfigurationIcon />,
|
||||
),
|
||||
];
|
||||
}, [getItem]);
|
||||
@ -93,16 +92,17 @@ const KnowledgeSidebar = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
useFetchKnowledgeBaseConfiguration();
|
||||
|
||||
return (
|
||||
<div className={styles.sidebarWrapper}>
|
||||
<div className={styles.sidebarTop}>
|
||||
<Space size={8} direction="vertical">
|
||||
<Avatar size={64} icon={<AntDesignOutlined />} />
|
||||
<div className={styles.knowledgeTitle}>Cloud Computing</div>
|
||||
<Avatar size={64} src={knowledgeDetails.avatar} />
|
||||
<div className={styles.knowledgeTitle}>{knowledgeDetails.name}</div>
|
||||
</Space>
|
||||
<p className={styles.knowledgeDescription}>
|
||||
A scalable, secure cloud-based database optimized for high-performance
|
||||
computing and data storage.
|
||||
{knowledgeDetails.description}
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.divider}></div>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { ITenantInfo } from '@/interfaces/database/knowledge';
|
||||
import { IThirdOAIModelCollection as IThirdAiModelCollection } from '@/interfaces/database/llm';
|
||||
import userService from '@/services/userService';
|
||||
import authorizationUtil from '@/utils/authorizationUtil';
|
||||
import { message } from 'antd';
|
||||
@ -12,7 +13,7 @@ export interface SettingModelState {
|
||||
isShowSSModal: boolean;
|
||||
llm_factory: string;
|
||||
tenantIfo: Nullable<ITenantInfo>;
|
||||
llmInfo: any;
|
||||
llmInfo: IThirdAiModelCollection;
|
||||
myLlm: any[];
|
||||
factoriesList: any[];
|
||||
}
|
||||
@ -126,8 +127,8 @@ const model: DvaModel<SettingModelState> = {
|
||||
}
|
||||
},
|
||||
*llm_list({ payload = {} }, { call, put }) {
|
||||
const { data, response } = yield call(userService.llm_list, payload);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
const { data } = yield call(userService.llm_list, payload);
|
||||
const { retcode, data: res } = data;
|
||||
if (retcode === 0) {
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
|
||||
Reference in New Issue
Block a user