mirror of
https://github.com/RYDE-WORK/Langchain-Chatchat.git
synced 2026-02-08 07:53:29 +08:00
知识库更改:知识库文档上传、删除、重构向量库、下载文档、按钮增加小图标
This commit is contained in:
parent
54dfef4796
commit
7e5a093641
13
frontend/src/app/api/knowledge/delVectorDocs/route.ts
Normal file
13
frontend/src/app/api/knowledge/delVectorDocs/route.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { getServerConfig } from '@/config/server';
|
||||||
|
const { KNOWLEDGE_PROXY_URL } = getServerConfig();
|
||||||
|
export const POST = async (request: Request) => {
|
||||||
|
const params = await request.json();
|
||||||
|
const fetchRes = await fetch(`${KNOWLEDGE_PROXY_URL}/delete_docs`, {
|
||||||
|
body: JSON.stringify(params),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
return fetchRes
|
||||||
|
};
|
||||||
13
frontend/src/app/api/knowledge/deleteDocs/route.ts
Normal file
13
frontend/src/app/api/knowledge/deleteDocs/route.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { getServerConfig } from '@/config/server';
|
||||||
|
const { KNOWLEDGE_PROXY_URL } = getServerConfig();
|
||||||
|
export const POST = async (request: Request) => {
|
||||||
|
const params = await request.json();
|
||||||
|
const fetchRes = await fetch(`${KNOWLEDGE_PROXY_URL}/delete_docs`, {
|
||||||
|
body: JSON.stringify(params),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
return fetchRes
|
||||||
|
};
|
||||||
13
frontend/src/app/api/knowledge/downloadDocs/route.ts
Normal file
13
frontend/src/app/api/knowledge/downloadDocs/route.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { getServerConfig } from '@/config/server';
|
||||||
|
const { KNOWLEDGE_PROXY_URL } = getServerConfig();
|
||||||
|
|
||||||
|
export const GET = async (request: Request) => {
|
||||||
|
const searchParams = new URL(request.url).searchParams;
|
||||||
|
const knowledge_base_name = searchParams.get('knowledge_base_name') as string;
|
||||||
|
const file_name = searchParams.get('file_name') as string;
|
||||||
|
const preview = searchParams.get('preview') as string;
|
||||||
|
|
||||||
|
const queryString = new URLSearchParams({ knowledge_base_name, file_name, preview }).toString();
|
||||||
|
const fetchRes = await fetch(`${KNOWLEDGE_PROXY_URL}/download_doc?${queryString}`);
|
||||||
|
return fetchRes;
|
||||||
|
};
|
||||||
9
frontend/src/app/api/knowledge/listFiles/route.ts
Normal file
9
frontend/src/app/api/knowledge/listFiles/route.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { getServerConfig } from '@/config/server';
|
||||||
|
|
||||||
|
const { KNOWLEDGE_PROXY_URL } = getServerConfig();
|
||||||
|
export const GET = async (request: Request) => {
|
||||||
|
const knowledge_base_name: string = new URL(request.url).searchParams.get('knowledge_base_name') as string;
|
||||||
|
const queryString = new URLSearchParams({ knowledge_base_name }).toString();
|
||||||
|
const fetchRes = await fetch(`${KNOWLEDGE_PROXY_URL}/list_files?${queryString}`);
|
||||||
|
return fetchRes;
|
||||||
|
};
|
||||||
14
frontend/src/app/api/knowledge/reAddVectorDB/route.ts
Normal file
14
frontend/src/app/api/knowledge/reAddVectorDB/route.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
import { getServerConfig } from '@/config/server';
|
||||||
|
const { KNOWLEDGE_PROXY_URL } = getServerConfig();
|
||||||
|
export const POST = async (request: Request) => {
|
||||||
|
const params = await request.json();
|
||||||
|
const fetchRes = await fetch(`${KNOWLEDGE_PROXY_URL}/recreate_vector_store`, {
|
||||||
|
body: JSON.stringify(params),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
return fetchRes
|
||||||
|
};
|
||||||
14
frontend/src/app/api/knowledge/rebuildVectorDB/route.ts
Normal file
14
frontend/src/app/api/knowledge/rebuildVectorDB/route.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
import { getServerConfig } from '@/config/server';
|
||||||
|
const { KNOWLEDGE_PROXY_URL } = getServerConfig();
|
||||||
|
export const POST = async (request: Request) => {
|
||||||
|
const params = await request.json();
|
||||||
|
const fetchRes = await fetch(`${KNOWLEDGE_PROXY_URL}/recreate_vector_store`, {
|
||||||
|
body: JSON.stringify(params),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
return fetchRes
|
||||||
|
};
|
||||||
12
frontend/src/app/api/knowledge/uploadDocs/route.ts
Normal file
12
frontend/src/app/api/knowledge/uploadDocs/route.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
import { getServerConfig } from '@/config/server';
|
||||||
|
const { KNOWLEDGE_PROXY_URL } = getServerConfig();
|
||||||
|
|
||||||
|
export const POST = async (request: Request) => {
|
||||||
|
const formData = await request.formData();
|
||||||
|
const fetchRes = await fetch(`${KNOWLEDGE_PROXY_URL}/upload_docs`, {
|
||||||
|
body: formData,
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
return fetchRes
|
||||||
|
};
|
||||||
@ -1,3 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
1. 创建接口没有简介字段
|
|
||||||
@ -2,7 +2,7 @@ import { DeleteOutlined, EditOutlined, ExclamationCircleOutlined } from '@ant-de
|
|||||||
import { Card, Skeleton, message, Modal } from 'antd';
|
import { Card, Skeleton, message, Modal } from 'antd';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useKnowledgeStore } from '@/store/knowledge';
|
import { useKnowledgeStore } from '@/store/knowledge';
|
||||||
|
|
||||||
const { Meta } = Card;
|
const { Meta } = Card;
|
||||||
|
|
||||||
@ -11,16 +11,18 @@ interface KnowLedgeCardProps {
|
|||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
const KnowledgeCard: React.FC<KnowLedgeCardProps> = (props: KnowLedgeCardProps) => {
|
const KnowledgeCard: React.FC<KnowLedgeCardProps> = (props: KnowLedgeCardProps) => {
|
||||||
|
|
||||||
|
|
||||||
const [useFetchKnowledgeDel] = useKnowledgeStore((s) => [
|
const [useFetchKnowledgeDel, useFetchKnowledgeList] = useKnowledgeStore((s) => [
|
||||||
s.useFetchKnowledgeDel
|
s.useFetchKnowledgeDel, s.useFetchKnowledgeList
|
||||||
]);
|
]);
|
||||||
|
const { mutate } = useFetchKnowledgeList()
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const { name, intro } = props;
|
const { name, intro } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const handleCardEditClick = () => {
|
const handleCardEditClick = () => {
|
||||||
router.push('/knowledge/1/base');
|
router.push(`/knowledge/${encodeURIComponent(name)}/base`);
|
||||||
};
|
};
|
||||||
const delClick = async () => {
|
const delClick = async () => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
@ -31,7 +33,8 @@ const KnowledgeCard: React.FC<KnowLedgeCardProps> = (props: KnowLedgeCardProps)
|
|||||||
if (resCode !== 200) {
|
if (resCode !== 200) {
|
||||||
message.error(resMsg)
|
message.error(resMsg)
|
||||||
} else {
|
} else {
|
||||||
message.success(resMsg)
|
message.success(resMsg)
|
||||||
|
mutate()
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
|
|||||||
@ -20,11 +20,6 @@ const useStyles = createStyles(({ css, token, stylish }) => ({
|
|||||||
`,
|
`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// const list = [
|
|
||||||
// { intro: '知识库简介', name: '知识库名称' },
|
|
||||||
// { intro: '知识库简介', name: '知识库名称' },
|
|
||||||
// ];
|
|
||||||
|
|
||||||
const RenderList = memo(() => {
|
const RenderList = memo(() => {
|
||||||
const { styles } = useStyles();
|
const { styles } = useStyles();
|
||||||
const [listData, useFetchKnowledgeList] = useKnowledgeStore((s) => [
|
const [listData, useFetchKnowledgeList] = useKnowledgeStore((s) => [
|
||||||
@ -32,11 +27,15 @@ const RenderList = memo(() => {
|
|||||||
]);
|
]);
|
||||||
const { isLoading } = useFetchKnowledgeList();
|
const { isLoading } = useFetchKnowledgeList();
|
||||||
|
|
||||||
const list = listData.map((item) => ({
|
const list = listData.map(({ kb_info, kb_name }) => ({
|
||||||
intro: '知识库简介',
|
intro: kb_info,
|
||||||
// 等接口更改...
|
name: kb_name
|
||||||
name: item as unknown as string
|
|
||||||
}))
|
}))
|
||||||
|
// const list = [
|
||||||
|
// { intro: '知识库简介', name: '知识库名称' },
|
||||||
|
// { intro: '知识库简介', name: '知识库名称' },
|
||||||
|
// ];
|
||||||
|
|
||||||
if (!isLoading && !listData.length) {
|
if (!isLoading && !listData.length) {
|
||||||
return <div className={styles.null}>
|
return <div className={styles.null}>
|
||||||
<Empty />
|
<Empty />
|
||||||
|
|||||||
@ -1,37 +1,43 @@
|
|||||||
import { Modal, type ModalProps } from '@lobehub/ui';
|
import { Modal, type ModalProps } from '@lobehub/ui';
|
||||||
import { Form, Input, Select, FormInstance, message } from 'antd';
|
import { Form, Input, Select, FormInstance, message } from 'antd';
|
||||||
import { memo, useRef } from 'react';
|
import { memo, useRef, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Flexbox } from 'react-layout-kit';
|
import { Flexbox } from 'react-layout-kit';
|
||||||
|
|
||||||
import { useKnowledgeStore } from '@/store/knowledge';
|
import { useKnowledgeStore } from '@/store/knowledge';
|
||||||
|
|
||||||
const DEFAULT_FIELD_VALUE = {
|
const DEFAULT_FIELD_VALUE = {
|
||||||
vector_store_type: "faiss",
|
vector_store_type: "faiss",
|
||||||
embed_model:"bge-large-zh-v1.5"
|
embed_model: "bge-large-zh-v1.5"
|
||||||
};
|
};
|
||||||
interface ModalCreateKnowledgeProps extends ModalProps {
|
interface ModalCreateKnowledgeProps extends ModalProps {
|
||||||
toggleModal: (open: boolean) => void;
|
toggleModal: (open: boolean) => void;
|
||||||
}
|
}
|
||||||
const CreateKnowledgeBase = memo<ModalCreateKnowledgeProps>(({ toggleModal, open }) => {
|
const CreateKnowledgeBase = memo<ModalCreateKnowledgeProps>(({ toggleModal, open }) => {
|
||||||
|
const [confirmLoading, setConfirmLoading] = useState(false);
|
||||||
const { t } = useTranslation('chat');
|
const { t } = useTranslation('chat');
|
||||||
const antdFormInstance = useRef<FormInstance>();
|
const antdFormInstance = useRef<FormInstance>();
|
||||||
const [useFetchKnowledgeAdd] = useKnowledgeStore((s) => [
|
const [useFetchKnowledgeAdd, useFetchKnowledgeList] = useKnowledgeStore((s) => [
|
||||||
s.useFetchKnowledgeAdd
|
s.useFetchKnowledgeAdd, s.useFetchKnowledgeList
|
||||||
]);
|
]);
|
||||||
|
const { mutate } = useFetchKnowledgeList()
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
if(!antdFormInstance.current) return;
|
if (!antdFormInstance.current) return;
|
||||||
const fieldsError = await antdFormInstance.current.validateFields();
|
const fieldsError = await antdFormInstance.current.validateFields();
|
||||||
if(fieldsError.length) return;
|
if (fieldsError.length) return;
|
||||||
const values = antdFormInstance.current.getFieldsValue(true);
|
const values = antdFormInstance.current.getFieldsValue(true);
|
||||||
|
|
||||||
const { code:resCode, data: resData, msg: resMsg } = await useFetchKnowledgeAdd({ ...values })
|
setConfirmLoading(true);
|
||||||
if(resCode !== 200){
|
const { code: resCode, data: resData, msg: resMsg } = await useFetchKnowledgeAdd({ ...values })
|
||||||
|
setConfirmLoading(true);
|
||||||
|
|
||||||
|
if (resCode !== 200) {
|
||||||
message.error(resMsg)
|
message.error(resMsg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
toggleModal(false);
|
mutate();
|
||||||
|
toggleModal(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -43,10 +49,11 @@ const CreateKnowledgeBase = memo<ModalCreateKnowledgeProps>(({ toggleModal, open
|
|||||||
onOk={onSubmit}
|
onOk={onSubmit}
|
||||||
open={open}
|
open={open}
|
||||||
title="创建知识库"
|
title="创建知识库"
|
||||||
|
confirmLoading={confirmLoading}
|
||||||
>
|
>
|
||||||
<Form initialValues={DEFAULT_FIELD_VALUE} layout="vertical" ref={antdFormInstance}>
|
<Form initialValues={DEFAULT_FIELD_VALUE} layout="vertical" ref={antdFormInstance}>
|
||||||
<Form.Item label="知识库名称" name="knowledge_base_name" rules={[{ required: true, message: '请输入知识库名称' }]}>
|
<Form.Item label="知识库名称" name="knowledge_base_name" rules={[{ required: true, message: '请输入知识库名称' }]}>
|
||||||
<Input autoFocus/>
|
<Input autoFocus />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="知识库简介" name="kb_info">
|
<Form.Item label="知识库简介" name="kb_info">
|
||||||
<Input />
|
<Input />
|
||||||
@ -54,7 +61,7 @@ const CreateKnowledgeBase = memo<ModalCreateKnowledgeProps>(({ toggleModal, open
|
|||||||
<Flexbox direction="horizontal" gap={10} justify="space-between">
|
<Flexbox direction="horizontal" gap={10} justify="space-between">
|
||||||
<div style={{ flex: '1' }}>
|
<div style={{ flex: '1' }}>
|
||||||
<Form.Item label="向量库类型" name="vector_store_type" rules={[{ required: true, message: '请选择向量库类型' }]}>
|
<Form.Item label="向量库类型" name="vector_store_type" rules={[{ required: true, message: '请选择向量库类型' }]}>
|
||||||
<Select>
|
<Select>
|
||||||
<Select.Option value="faiss">faiss</Select.Option>
|
<Select.Option value="faiss">faiss</Select.Option>
|
||||||
<Select.Option value="milvus">milvus</Select.Option>
|
<Select.Option value="milvus">milvus</Select.Option>
|
||||||
<Select.Option value="zilliz">zilliz</Select.Option>
|
<Select.Option value="zilliz">zilliz</Select.Option>
|
||||||
@ -66,9 +73,9 @@ const CreateKnowledgeBase = memo<ModalCreateKnowledgeProps>(({ toggleModal, open
|
|||||||
</div>
|
</div>
|
||||||
<div style={{ flex: '1' }}>
|
<div style={{ flex: '1' }}>
|
||||||
<Form.Item label="Embedding模型" name="embed_model" rules={[{ required: true, message: '请选择Embedding模型' }]}>
|
<Form.Item label="Embedding模型" name="embed_model" rules={[{ required: true, message: '请选择Embedding模型' }]}>
|
||||||
<Select>
|
<Select>
|
||||||
<Select.Option value="bge-large-zh-v1.5">bge-large-zh-v1.5</Select.Option>
|
<Select.Option value="bge-large-zh-v1.5">bge-large-zh-v1.5</Select.Option>
|
||||||
<Select.Option value="text-embedding-v1">text-embedding-v1</Select.Option>
|
<Select.Option value="text-embedding-v1">text-embedding-v1</Select.Option>
|
||||||
<Select.Option value="Bert">Bert</Select.Option>
|
<Select.Option value="Bert">Bert</Select.Option>
|
||||||
<Select.Option value="Word2Vec">Word2Vec</Select.Option>
|
<Select.Option value="Word2Vec">Word2Vec</Select.Option>
|
||||||
<Select.Option value="FastText">FastText</Select.Option>
|
<Select.Option value="FastText">FastText</Select.Option>
|
||||||
|
|||||||
@ -1,48 +1,154 @@
|
|||||||
import { InboxOutlined } from '@ant-design/icons';
|
import { InboxOutlined } from '@ant-design/icons';
|
||||||
import type { UploadProps } from 'antd';
|
import { Form, Modal, Upload, InputNumber, Radio, message } from 'antd';
|
||||||
import { Modal, Upload, message } from 'antd';
|
import React, { memo, useState } from 'react';
|
||||||
import React, { memo } from 'react';
|
import { useKnowledgeStore } from '@/store/knowledge';
|
||||||
|
import type { GetProp, UploadFile, UploadProps } from 'antd';
|
||||||
const { Dragger } = Upload;
|
|
||||||
|
|
||||||
type ModalAddFileProps = {
|
type ModalAddFileProps = {
|
||||||
|
kbName: string;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
setModalOpen: (open: boolean) => void;
|
setModalOpen: (open: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];
|
||||||
|
|
||||||
const props: UploadProps = {
|
const ModalAddFile = memo<ModalAddFileProps>(({ open, setModalOpen, kbName }) => {
|
||||||
action: 'https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload',
|
const [confirmLoading, setConfirmLoading] = useState(false);
|
||||||
multiple: true,
|
const [antdFormInstance] = Form.useForm();
|
||||||
name: 'file',
|
const [useFetchKnowledgeUploadDocs, useFetchKnowledgeFilesList] = useKnowledgeStore((s) => [
|
||||||
onChange(info) {
|
s.useFetchKnowledgeUploadDocs, s.useFetchKnowledgeFilesList
|
||||||
const { status } = info.file;
|
]);
|
||||||
if (status !== 'uploading') {
|
const { mutate } = useFetchKnowledgeFilesList(kbName)
|
||||||
console.log(info.file, info.fileList);
|
const [fileList, setFileList] = useState<UploadFile[]>([]);
|
||||||
}
|
|
||||||
if (status === 'done') {
|
const antdUploadProps: UploadProps = {
|
||||||
message.success(`${info.file.name} file uploaded successfully.`);
|
name: "files",
|
||||||
} else if (status === 'error') {
|
onRemove: (file) => {
|
||||||
message.error(`${info.file.name} file upload failed.`);
|
const index = fileList.indexOf(file);
|
||||||
}
|
const newFileList = fileList.slice();
|
||||||
},
|
newFileList.splice(index, 1);
|
||||||
onDrop(e) {
|
setFileList(newFileList);
|
||||||
console.log('Dropped files', e.dataTransfer.files);
|
},
|
||||||
},
|
beforeUpload: (file) => {
|
||||||
};
|
setFileList([...fileList, file]);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
fileList,
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = async () => {
|
||||||
|
if (!antdFormInstance) return;
|
||||||
|
const fieldsError = await antdFormInstance.validateFields();
|
||||||
|
if (fieldsError.length) return;
|
||||||
|
const values = antdFormInstance.getFieldsValue(true);
|
||||||
|
if(!fileList.length){
|
||||||
|
message.error('请选择文件')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
fileList.forEach((file) => {
|
||||||
|
formData.append('files', file as FileType);
|
||||||
|
});
|
||||||
|
for (const key in values) {
|
||||||
|
formData.append(key, values[key]);
|
||||||
|
}
|
||||||
|
formData.append('knowledge_base_name', kbName);
|
||||||
|
|
||||||
|
setConfirmLoading(true);
|
||||||
|
const { code: resCode, data: resData, msg: resMsg } = await useFetchKnowledgeUploadDocs(formData)
|
||||||
|
setConfirmLoading(true);
|
||||||
|
|
||||||
|
if (resCode !== 200) {
|
||||||
|
message.error(resMsg)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
message.success(resMsg)
|
||||||
|
mutate();
|
||||||
|
setModalOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const layout = {
|
||||||
|
labelCol: { span: 10 },
|
||||||
|
wrapperCol: { span: 14 },
|
||||||
|
}
|
||||||
|
|
||||||
const ModalAddFile = memo<ModalAddFileProps>(({ open, setModalOpen }) => {
|
|
||||||
return (
|
return (
|
||||||
<Modal onCancel={() => setModalOpen(false)} open={open} title="添加文件">
|
<Modal
|
||||||
<Dragger {...props}>
|
onCancel={() => setModalOpen(false)}
|
||||||
<p className="ant-upload-drag-icon">
|
open={open} title="添加文件"
|
||||||
<InboxOutlined />
|
onOk={onSubmit}
|
||||||
</p>
|
confirmLoading={confirmLoading}
|
||||||
<p className="ant-upload-text">Click or drag file to this area to upload</p>
|
width={600}
|
||||||
<p className="ant-upload-hint">
|
>
|
||||||
Support for a single or bulk upload. Strictly prohibited from uploading company data or
|
|
||||||
other banned files.
|
<Form
|
||||||
</p>
|
name="validate_other"
|
||||||
</Dragger>
|
initialValues={{
|
||||||
|
override: true,
|
||||||
|
chunk_size: 0,
|
||||||
|
chunk_overlap: 0,
|
||||||
|
to_vector_store: true,
|
||||||
|
}}
|
||||||
|
form={antdFormInstance}
|
||||||
|
>
|
||||||
|
|
||||||
|
<div style={{ padding: `24px 0px` }}>
|
||||||
|
<Upload.Dragger {...antdUploadProps}>
|
||||||
|
<p className="ant-upload-drag-icon">
|
||||||
|
<InboxOutlined />
|
||||||
|
</p>
|
||||||
|
<p className="ant-upload-text">单击或拖动文件到此区域进行上传</p>
|
||||||
|
<p className="ant-upload-hint">支持单个或批量上传。</p>
|
||||||
|
</Upload.Dragger>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Form.Item name="override" label="覆盖已有文件" {...layout}>
|
||||||
|
<Radio.Group>
|
||||||
|
<Radio value={true}>是</Radio>
|
||||||
|
<Radio value={false}>否</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item name="to_vector_store" label="上传文件后是否进行向量化" {...layout}>
|
||||||
|
<Radio.Group>
|
||||||
|
<Radio value={true}>是</Radio>
|
||||||
|
<Radio value={false}>否</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="zh_title_enhance" label="是否开启中文标题加强" {...layout}>
|
||||||
|
<Radio.Group>
|
||||||
|
<Radio value={true}>是</Radio>
|
||||||
|
<Radio value={false}>否</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="not_refresh_vs_cache" label="暂不保存向量库(用于FAISS)" {...layout}>
|
||||||
|
<Radio.Group>
|
||||||
|
<Radio value={true}>是</Radio>
|
||||||
|
<Radio value={false}>否</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
|
||||||
|
<Form.Item label="知识库中单段文本最大长度" {...layout} {...layout}>
|
||||||
|
<Form.Item name="chunk_size">
|
||||||
|
<InputNumber min={0} />
|
||||||
|
</Form.Item>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item label="知识库中相邻文本重合长度" {...layout} {...layout}>
|
||||||
|
<Form.Item name="chunk_overlap">
|
||||||
|
<InputNumber min={0} />
|
||||||
|
</Form.Item>
|
||||||
|
</Form.Item>
|
||||||
|
{/* <Form.Item label="自定义的docs">
|
||||||
|
<Form.Item name="docs">
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
</Form.Item> */}
|
||||||
|
|
||||||
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,37 +1,69 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Button, Table } from 'antd';
|
import { Button, Table, message, Spin, Modal } from 'antd';
|
||||||
import type { TableColumnsType } from 'antd';
|
import type { TableColumnsType } from 'antd';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Flexbox } from 'react-layout-kit';
|
import { Flexbox } from 'react-layout-kit';
|
||||||
|
import { useKnowledgeStore } from '@/store/knowledge';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { UndoOutlined, DeleteOutlined, DownloadOutlined, PlusOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
// import ModalAddFile from './features/ModalAddFile';
|
|
||||||
const ModalAddFile = dynamic(() => import('./features/ModalAddFile'));
|
const ModalAddFile = dynamic(() => import('./features/ModalAddFile'));
|
||||||
interface DataType {
|
interface DataType {
|
||||||
address: string;
|
id: React.Key;
|
||||||
age: number;
|
|
||||||
key: React.Key;
|
|
||||||
name: string;
|
name: string;
|
||||||
|
loader: string;
|
||||||
|
splitter: string;
|
||||||
|
source: string;
|
||||||
|
vector: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data: DataType[] = [];
|
const App: React.FC<{ params: { id: string } }> = ({ params }) => {
|
||||||
for (let i = 0; i < 46; i++) {
|
const router = useRouter();
|
||||||
data.push({
|
const [
|
||||||
address: `London, Park Lane no. ${i}`,
|
filesData,
|
||||||
age: 32,
|
useFetchKnowledgeFilesList,
|
||||||
index: i,
|
useFetchKnowledgeDownloadDocs,
|
||||||
key: i,
|
useFetcDelInknowledgeDB,
|
||||||
name: `Edward King ${i}`,
|
useFetcRebuildVectorDB,
|
||||||
});
|
useFetchKnowledgeDel
|
||||||
}
|
|
||||||
|
|
||||||
const App: React.FC<{ params }> = ({ params }) => {
|
] = useKnowledgeStore((s) => [
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
s.filesData,
|
||||||
|
s.useFetchKnowledgeFilesList,
|
||||||
|
s.useFetchKnowledgeDownloadDocs,
|
||||||
|
s.useFetcDelInknowledgeDB,
|
||||||
|
s.useFetcRebuildVectorDB,
|
||||||
|
s.useFetchKnowledgeDel
|
||||||
|
]);
|
||||||
|
const { isLoading } = useFetchKnowledgeFilesList(params.id);
|
||||||
|
|
||||||
|
const [downloadLoading, setDownloadLoading] = useState(false);
|
||||||
|
const [delDocsLoading, setDelDocsLoading] = useState(false);
|
||||||
|
const [rebuildVectorDBLoading, setRebuildVectorDBLoading] = useState(false);
|
||||||
|
|
||||||
|
// rebuild progress
|
||||||
|
const [rebuildProgress, setRebuildProgress] = useState("0%");
|
||||||
|
|
||||||
|
// const data: DataType[] = filesData.map((item, i) => ({
|
||||||
|
// id: i, // item 应该为对象,待提交问题...
|
||||||
|
// name: item, // item 应该为对象,待提交问题...
|
||||||
|
// loader: "",
|
||||||
|
// splitter: "",
|
||||||
|
// source: "",
|
||||||
|
// vector: ""
|
||||||
|
// }));
|
||||||
|
const data = [
|
||||||
|
{ id: '1', name: 'name1', loader: "loader", splitter: "splitter", source: "source", vector: "vector" },
|
||||||
|
{ id: '2', name: 'name2', loader: "loader", splitter: "splitter", source: "source", vector: "vector" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [isShowModal, setModal] = useState(false);
|
const [isShowModal, setModal] = useState(false);
|
||||||
const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
|
const onSelectChange = (newSelectedRowKeys: string[]) => {
|
||||||
console.log('selectedRowKeys changed:', newSelectedRowKeys);
|
console.log('selectedRowKeys changed:', newSelectedRowKeys);
|
||||||
setSelectedRowKeys(newSelectedRowKeys);
|
setSelectedRowKeys(newSelectedRowKeys);
|
||||||
};
|
};
|
||||||
@ -42,17 +74,13 @@ const App: React.FC<{ params }> = ({ params }) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
render: (text) => <Link href={`/knowledge/${params.id}/base/2`}>{text}</Link>,
|
render: (text, rowData) => <Link href={`/knowledge/${params.id}/base/${rowData.id}`}>{text}</Link>,
|
||||||
title: '文档名称',
|
title: '文档名称',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'loader',
|
dataIndex: 'loader',
|
||||||
title: '文档加载器',
|
title: '文档加载器',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
dataIndex: 'loader',
|
|
||||||
title: '文档加载器',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
dataIndex: 'splitter',
|
dataIndex: 'splitter',
|
||||||
title: '分词器',
|
title: '分词器',
|
||||||
@ -71,40 +99,126 @@ const App: React.FC<{ params }> = ({ params }) => {
|
|||||||
selectedRowKeys,
|
selectedRowKeys,
|
||||||
};
|
};
|
||||||
const hasSelected = selectedRowKeys.length > 0;
|
const hasSelected = selectedRowKeys.length > 0;
|
||||||
console.log(params);
|
|
||||||
|
const download = async () => {
|
||||||
|
setDownloadLoading(true);
|
||||||
|
for (const docName of selectedRowKeys) {
|
||||||
|
await useFetchKnowledgeDownloadDocs(params.id, docName).catch(() => {
|
||||||
|
message.error(`下载 ${docName} 失败`);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
setDownloadLoading(false);
|
||||||
|
};
|
||||||
|
const reAddVectorDB = async () => {
|
||||||
|
console.log('reAddShapeDB: ', selectedRowKeys);
|
||||||
|
}
|
||||||
|
const rebuildVectorDB = async () => {
|
||||||
|
console.log('rebuildVectorDB ');
|
||||||
|
setRebuildVectorDBLoading(true);
|
||||||
|
try {
|
||||||
|
useFetcRebuildVectorDB({
|
||||||
|
"knowledge_base_name": params.id,
|
||||||
|
"allow_empty_kb": true,
|
||||||
|
"vs_type": "faiss",
|
||||||
|
"embed_model": "text-embedding-v1",
|
||||||
|
"chunk_size": 250,
|
||||||
|
"chunk_overlap": 50,
|
||||||
|
"zh_title_enhance": false,
|
||||||
|
"not_refresh_vs_cache": false,
|
||||||
|
}, {
|
||||||
|
onFinish: async () => {
|
||||||
|
message.success(`重建向量库成功`);
|
||||||
|
setRebuildVectorDBLoading(false);
|
||||||
|
},
|
||||||
|
onMessageHandle: (text) => {
|
||||||
|
setRebuildProgress(text)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
message.error(`请求错误`);
|
||||||
|
}
|
||||||
|
setRebuildVectorDBLoading(false);
|
||||||
|
}
|
||||||
|
const delInVectorDB = async () => {
|
||||||
|
console.log('delInShapeDB: ', selectedRowKeys);
|
||||||
|
|
||||||
|
setSelectedRowKeys([]);
|
||||||
|
}
|
||||||
|
const delInknowledgeDB = async () => {
|
||||||
|
setDelDocsLoading(true);
|
||||||
|
await useFetcDelInknowledgeDB({
|
||||||
|
"knowledge_base_name": params.id,
|
||||||
|
"file_names": [...selectedRowKeys],
|
||||||
|
"delete_content": false,
|
||||||
|
"not_refresh_vs_cache": false
|
||||||
|
}).catch(() => {
|
||||||
|
message.error(`删除失败`);
|
||||||
|
})
|
||||||
|
setDelDocsLoading(false);
|
||||||
|
setSelectedRowKeys([]);
|
||||||
|
}
|
||||||
|
const delKnowledge = async () => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: `确认 ${params.id} 删除吗?`,
|
||||||
|
icon: <ExclamationCircleOutlined />,
|
||||||
|
async onOk() {
|
||||||
|
const { code: resCode, msg: resMsg } = await useFetchKnowledgeDel(params.id)
|
||||||
|
if (resCode !== 200) {
|
||||||
|
message.error(resMsg)
|
||||||
|
} else {
|
||||||
|
message.success(resMsg);
|
||||||
|
router.push('/knowledge')
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Flexbox width={'100%'}>
|
<Flexbox width={'100%'}>
|
||||||
<Flexbox direction="horizontal" justify="space-between" style={{ marginBottom: 16 }}>
|
<Flexbox direction="horizontal" justify="space-between" style={{ marginBottom: 16 }}>
|
||||||
<Flexbox direction="horizontal" gap={20}>
|
<Flexbox direction="horizontal" gap={20}>
|
||||||
<Button disabled={!hasSelected} loading={loading} type="default">
|
<Button disabled={!hasSelected} loading={downloadLoading} type="default" onClick={download} icon={<DownloadOutlined />}>
|
||||||
下载选中文档
|
下载选中文档
|
||||||
</Button>
|
</Button>
|
||||||
<Button disabled={!hasSelected} loading={loading} type="default">
|
<Button disabled={!hasSelected} loading={loading} type="default" onClick={reAddVectorDB}>
|
||||||
重新添加至向量库
|
重新添加至向量库
|
||||||
</Button>
|
</Button>
|
||||||
<Button disabled={!hasSelected} loading={loading} type="default">
|
<Button danger disabled={!hasSelected} loading={loading} type="default" onClick={delInVectorDB} icon={<DeleteOutlined />}>
|
||||||
向量库删除
|
向量库删除
|
||||||
</Button>
|
</Button>
|
||||||
<Button disabled={!hasSelected} loading={loading} type="default">
|
<Button danger disabled={!hasSelected} loading={delDocsLoading} type="default" onClick={delInknowledgeDB} icon={<DeleteOutlined />}>
|
||||||
从知识库中删除
|
从知识库中删除
|
||||||
</Button>
|
</Button>
|
||||||
</Flexbox>
|
</Flexbox>
|
||||||
<div>
|
<Flexbox direction="horizontal" gap={20}>
|
||||||
<Button loading={loading} onClick={() => setModal(true)} type="primary">
|
<Button danger loading={loading} onClick={delKnowledge} type="primary" icon={<DeleteOutlined />}>
|
||||||
|
删除知识库
|
||||||
|
</Button>
|
||||||
|
<Button loading={loading} onClick={() => setModal(true)} type="primary" icon={<PlusOutlined />}>
|
||||||
添加文件
|
添加文件
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</Flexbox>
|
||||||
</Flexbox>
|
</Flexbox>
|
||||||
<Table
|
<Spin spinning={rebuildVectorDBLoading} tip={rebuildProgress}>
|
||||||
columns={columns}
|
<Table
|
||||||
dataSource={data}
|
columns={columns}
|
||||||
rowSelection={rowSelection}
|
dataSource={data}
|
||||||
size="middle"
|
rowSelection={rowSelection}
|
||||||
style={{ width: '100%' }}
|
size="middle"
|
||||||
/>
|
style={{ width: '100%' }}
|
||||||
</Flexbox>
|
rowKey={"name"}
|
||||||
<ModalAddFile open={isShowModal} setModalOpen={setModal} />
|
loading={isLoading}
|
||||||
|
footer={() => <div>
|
||||||
|
<Button danger loading={rebuildVectorDBLoading} onClick={rebuildVectorDB} icon={<UndoOutlined />}>
|
||||||
|
依据源文件重建向量库
|
||||||
|
</Button>
|
||||||
|
</div>}
|
||||||
|
/>
|
||||||
|
</Spin>
|
||||||
|
</Flexbox >
|
||||||
|
<ModalAddFile open={isShowModal} setModalOpen={setModal} kbName={params.id} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -12,7 +12,7 @@ interface LayoutProps extends PropsWithChildren {
|
|||||||
params: Record<string, string>;
|
params: Record<string, string>;
|
||||||
}
|
}
|
||||||
export default memo<LayoutProps>(({ children, params }) => {
|
export default memo<LayoutProps>(({ children, params }) => {
|
||||||
console.log(params);
|
// console.log(params);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayoutDesktop sidebarKey={SidebarTabKey.Knowledge}>
|
<AppLayoutDesktop sidebarKey={SidebarTabKey.Knowledge}>
|
||||||
|
|||||||
@ -48,5 +48,13 @@ export const API_ENDPOINTS = mapWithBasePath({
|
|||||||
// knowledge
|
// knowledge
|
||||||
knowledgeList: '/api/knowledge/list',
|
knowledgeList: '/api/knowledge/list',
|
||||||
knowledgeAdd: '/api/knowledge/add',
|
knowledgeAdd: '/api/knowledge/add',
|
||||||
knowledgeDel: '/api/knowledge/del'
|
knowledgeDel: '/api/knowledge/del',
|
||||||
|
// knowledge files
|
||||||
|
knowledgeFilesList: '/api/knowledge/listFiles',
|
||||||
|
knowledgeUploadDocs: '/api/knowledge/uploadDocs',
|
||||||
|
knowledgeDownloadDocs: '/api/knowledge/downloadDocs',
|
||||||
|
knowledgeDelInknowledgeDB: '/api/knowledge/deleteDocs',
|
||||||
|
knowledgeRebuildVectorDB: '/api/knowledge/rebuildVectorDB',
|
||||||
|
knowledgeReAddVectorDB: '/api/knowledge/reAddVectorDB',
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,16 +1,21 @@
|
|||||||
|
|
||||||
import { KnowledgeList, KnowledgeFormFields, Reseponse } from '@/types/knowledge';
|
import type {
|
||||||
|
KnowledgeList, KnowledgeFormFields, Reseponse,
|
||||||
|
KnowledgeFilesList, KnowledgeDelDocsParams, KnowledgeDelDocsRes,
|
||||||
|
KnowledgeRebuildVectorParams, KnowledgeRebuildVectorRes
|
||||||
|
} from '@/types/knowledge';
|
||||||
|
|
||||||
|
import { fetchSSE, FetchSSEOptions } from '@/utils/fetch';
|
||||||
import { API_ENDPOINTS } from './_url';
|
import { API_ENDPOINTS } from './_url';
|
||||||
|
|
||||||
class KnowledgeService {
|
class KnowledgeService {
|
||||||
getList = async (): Promise<Reseponse<KnowledgeList>> => {
|
getList = async (): Promise<Reseponse<KnowledgeList>> => {
|
||||||
const res = await fetch(`${API_ENDPOINTS.knowledgeList}`);
|
const res = await fetch(`${API_ENDPOINTS.knowledgeList}`);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
add = async (formValues: KnowledgeFormFields) => {
|
add = async (formValues: KnowledgeFormFields) => {
|
||||||
const res = await fetch(`${API_ENDPOINTS.knowledgeAdd}`, {
|
const res = await fetch(`${API_ENDPOINTS.knowledgeAdd}`, {
|
||||||
body: JSON.stringify(formValues),
|
body: JSON.stringify(formValues),
|
||||||
headers: {
|
headers: {
|
||||||
@ -21,7 +26,7 @@ class KnowledgeService {
|
|||||||
return res.json();
|
return res.json();
|
||||||
};
|
};
|
||||||
|
|
||||||
del = async (name: string) => {
|
del = async (name: string) => {
|
||||||
const res = await fetch(`${API_ENDPOINTS.knowledgeDel}`, {
|
const res = await fetch(`${API_ENDPOINTS.knowledgeDel}`, {
|
||||||
body: JSON.stringify(name),
|
body: JSON.stringify(name),
|
||||||
headers: {
|
headers: {
|
||||||
@ -31,6 +36,96 @@ class KnowledgeService {
|
|||||||
});
|
});
|
||||||
return res.json();
|
return res.json();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getFilesList = (name: string): () => Promise<Reseponse<KnowledgeFilesList>> => {
|
||||||
|
const queryString = new URLSearchParams({
|
||||||
|
knowledge_base_name: name
|
||||||
|
}).toString();
|
||||||
|
return async () => {
|
||||||
|
const res = await fetch(`${API_ENDPOINTS.knowledgeFilesList}?${queryString}`);
|
||||||
|
const data = await res.json();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
uploadDocs = async (formData: FormData): Promise<Reseponse<{}>> => {
|
||||||
|
const res = await fetch(`${API_ENDPOINTS.knowledgeUploadDocs}`, {
|
||||||
|
body: formData,
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
delInknowledgeDB = async (params: KnowledgeDelDocsParams): Promise<Reseponse<KnowledgeDelDocsRes>> => {
|
||||||
|
const res = await fetch(`${API_ENDPOINTS.knowledgeDelInknowledgeDB}`, {
|
||||||
|
body: JSON.stringify({
|
||||||
|
...params,
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
rebuildVectorDB = async (params: KnowledgeRebuildVectorParams, opts:
|
||||||
|
{ onFinish: FetchSSEOptions["onFinish"]; onMessageHandle: FetchSSEOptions["onMessageHandle"] }
|
||||||
|
) => {
|
||||||
|
const { onFinish, onMessageHandle } = opts;
|
||||||
|
fetchSSE(async ()=> await fetch(`${API_ENDPOINTS.knowledgeRebuildVectorDB}`, {
|
||||||
|
body: JSON.stringify({
|
||||||
|
...params,
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
method: 'POST'
|
||||||
|
}), {
|
||||||
|
onErrorHandle: (error) => {
|
||||||
|
throw new Error('请求错误:' + error);
|
||||||
|
},
|
||||||
|
onFinish,
|
||||||
|
onMessageHandle
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
// delVectorDocs = async (formData: FormData): Promise<Reseponse<{}>> => {
|
||||||
|
// // const res = await fetch(`${API_ENDPOINTS.knowledgeUploadDocs}`, {
|
||||||
|
// // body: formData,
|
||||||
|
// // // headers: {
|
||||||
|
// // // 'Content-Type': 'application/json',
|
||||||
|
// // // },
|
||||||
|
// // method: 'POST',
|
||||||
|
// // });
|
||||||
|
// // return res.json();
|
||||||
|
// };
|
||||||
|
|
||||||
|
downloadDocs = async (kbName: string, docName: string): Promise<Reseponse<{}>> => {
|
||||||
|
const queryString = new URLSearchParams({
|
||||||
|
knowledge_base_name: kbName,
|
||||||
|
file_name: docName,
|
||||||
|
preview: 'false'
|
||||||
|
}).toString();
|
||||||
|
const res = await fetch(`${API_ENDPOINTS.knowledgeDownloadDocs}?${queryString}`);
|
||||||
|
console.log('res', res)
|
||||||
|
const data = await res.json();
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// reAddVectorDB = async (formData: FormData): Promise<Reseponse<{}>> => {
|
||||||
|
// // const res = await fetch(`${API_ENDPOINTS.knowledgeUploadDocs}`, {
|
||||||
|
// // body: formData,
|
||||||
|
// // // headers: {
|
||||||
|
// // // 'Content-Type': 'application/json',
|
||||||
|
// // // },
|
||||||
|
// // method: 'POST',
|
||||||
|
// // });
|
||||||
|
// // return res.json();
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const knowledgeService = new KnowledgeService();
|
export const knowledgeService = new KnowledgeService();
|
||||||
|
|||||||
@ -5,7 +5,13 @@ import type { StateCreator } from 'zustand/vanilla';
|
|||||||
import { knowledgeService } from '@/services/knowledge';
|
import { knowledgeService } from '@/services/knowledge';
|
||||||
|
|
||||||
import { globalHelpers } from '@/store/global/helpers';
|
import { globalHelpers } from '@/store/global/helpers';
|
||||||
import { KnowledgeFormFields, KnowledgeList, Reseponse } from '@/types/knowledge';
|
import {
|
||||||
|
KnowledgeFormFields, KnowledgeList, Reseponse, KnowledgeFilesList,
|
||||||
|
KnowledgeDelDocsParams, KnowledgeDelDocsRes,
|
||||||
|
KnowledgeRebuildVectorParams, KnowledgeRebuildVectorRes
|
||||||
|
|
||||||
|
} from '@/types/knowledge';
|
||||||
|
import type { FetchSSEOptions } from '@/utils/fetch';
|
||||||
|
|
||||||
import type { Store } from './store';
|
import type { Store } from './store';
|
||||||
|
|
||||||
@ -13,7 +19,19 @@ export interface StoreAction {
|
|||||||
listData: KnowledgeList;
|
listData: KnowledgeList;
|
||||||
useFetchKnowledgeList: () => SWRResponse<Reseponse<KnowledgeList>>;
|
useFetchKnowledgeList: () => SWRResponse<Reseponse<KnowledgeList>>;
|
||||||
useFetchKnowledgeAdd: (arg: KnowledgeFormFields) => Promise<Reseponse<KnowledgeFormFields>>;
|
useFetchKnowledgeAdd: (arg: KnowledgeFormFields) => Promise<Reseponse<KnowledgeFormFields>>;
|
||||||
useFetchKnowledgeDel: (name: string)=> Promise<Reseponse<{}>>;
|
useFetchKnowledgeDel: (name: string) => Promise<Reseponse<{}>>;
|
||||||
|
|
||||||
|
// files
|
||||||
|
filesData: KnowledgeFilesList;
|
||||||
|
useFetchKnowledgeFilesList: (name: string) => SWRResponse<Reseponse<KnowledgeFilesList>>;
|
||||||
|
useFetchKnowledgeUploadDocs: (arg: FormData) => Promise<Reseponse<{}>>;
|
||||||
|
useFetchKnowledgeDownloadDocs: (kbName: string, docName: string) => Promise<Reseponse<{}>>;
|
||||||
|
useFetcDelInknowledgeDB: (arg: KnowledgeDelDocsParams) => Promise<Reseponse<KnowledgeDelDocsRes>>;
|
||||||
|
useFetcRebuildVectorDB: (arg: KnowledgeRebuildVectorParams, options: {
|
||||||
|
onFinish: FetchSSEOptions["onFinish"];
|
||||||
|
onMessageHandle: FetchSSEOptions["onMessageHandle"]
|
||||||
|
}) => void;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createKnowledgeAction: StateCreator<
|
export const createKnowledgeAction: StateCreator<
|
||||||
@ -28,7 +46,7 @@ export const createKnowledgeAction: StateCreator<
|
|||||||
globalHelpers.getCurrentLanguage(),
|
globalHelpers.getCurrentLanguage(),
|
||||||
knowledgeService.getList,
|
knowledgeService.getList,
|
||||||
{
|
{
|
||||||
onSuccess: (res) => {
|
onSuccess: (res) => {
|
||||||
set({ listData: res.data })
|
set({ listData: res.data })
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -40,4 +58,31 @@ export const createKnowledgeAction: StateCreator<
|
|||||||
useFetchKnowledgeDel: async (name) => {
|
useFetchKnowledgeDel: async (name) => {
|
||||||
return await knowledgeService.del(name)
|
return await knowledgeService.del(name)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
filesData: [],
|
||||||
|
useFetchKnowledgeFilesList: (knowledge_base_name) => {
|
||||||
|
return useSWR<Reseponse<KnowledgeFilesList>>(
|
||||||
|
globalHelpers.getCurrentLanguage(),
|
||||||
|
knowledgeService.getFilesList(knowledge_base_name),
|
||||||
|
{
|
||||||
|
onSuccess: (res) => {
|
||||||
|
set({ filesData: res.data })
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
useFetchKnowledgeUploadDocs: (formData) => {
|
||||||
|
return knowledgeService.uploadDocs(formData);
|
||||||
|
},
|
||||||
|
useFetchKnowledgeDownloadDocs: (kbName: string, docName: string) => {
|
||||||
|
return knowledgeService.downloadDocs(kbName, docName);
|
||||||
|
},
|
||||||
|
useFetcDelInknowledgeDB: (params) => {
|
||||||
|
return knowledgeService.delInknowledgeDB(params);
|
||||||
|
},
|
||||||
|
useFetcRebuildVectorDB: (params, options) => {
|
||||||
|
return knowledgeService.rebuildVectorDB(params, options);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
export interface Reseponse <T> { code: number; msg: string; data: T }
|
export interface Reseponse<T> { code: number; msg: string; data: T }
|
||||||
|
|
||||||
|
|
||||||
|
// create Knowledge fields
|
||||||
export interface KnowledgeFormFields {
|
export interface KnowledgeFormFields {
|
||||||
knowledge_base_name: string;
|
knowledge_base_name: string;
|
||||||
vector_store_type: string;
|
vector_store_type: string;
|
||||||
@ -7,6 +9,49 @@ export interface KnowledgeFormFields {
|
|||||||
embed_model: string;
|
embed_model: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KnowledgeListItemFields extends KnowledgeFormFields { }
|
// Knowledge base list
|
||||||
|
export interface KnowledgeListFields {
|
||||||
|
"id": number;
|
||||||
|
"kb_name": string;
|
||||||
|
"kb_info": string;
|
||||||
|
"vs_type": string;
|
||||||
|
"embed_model": string;
|
||||||
|
"file_count": number;
|
||||||
|
"create_time": string;
|
||||||
|
}
|
||||||
|
export type KnowledgeList = KnowledgeListFields[];
|
||||||
|
|
||||||
|
// Knowledge base file list
|
||||||
|
export type KnowledgeFilesFields = string;
|
||||||
|
export type KnowledgeFilesList = KnowledgeFilesFields[];
|
||||||
|
|
||||||
|
// Example Delete parameters of the knowledge base file
|
||||||
|
export interface KnowledgeDelDocsParams {
|
||||||
|
knowledge_base_name: string;
|
||||||
|
file_names: string[];
|
||||||
|
delete_content: boolean;
|
||||||
|
not_refresh_vs_cache: boolean;
|
||||||
|
}
|
||||||
|
export interface KnowledgeDelDocsRes {
|
||||||
|
knowledge_base_name: string;
|
||||||
|
file_names: string[];
|
||||||
|
delete_content: boolean;
|
||||||
|
not_refresh_vs_cache: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Rebuild the vector library
|
||||||
|
export interface KnowledgeRebuildVectorParams {
|
||||||
|
"knowledge_base_name": string;
|
||||||
|
"allow_empty_kb": boolean;
|
||||||
|
"vs_type": string;
|
||||||
|
"embed_model": string
|
||||||
|
"chunk_size": number;
|
||||||
|
"chunk_overlap": number;
|
||||||
|
"zh_title_enhance": boolean;
|
||||||
|
"not_refresh_vs_cache": boolean;
|
||||||
|
}
|
||||||
|
export interface KnowledgeRebuildVectorRes { }
|
||||||
|
|
||||||
|
|
||||||
export type KnowledgeList = KnowledgeListItemFields[];
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user