知识库接口对接:知识库所有接口对接代码编写完毕。

This commit is contained in:
wangzongming 2024-06-04 11:09:31 +08:00
parent 7e5a093641
commit 32600650d3
12 changed files with 290 additions and 153 deletions

View File

@ -3,7 +3,7 @@ import { getServerConfig } from '@/config/server';
const { KNOWLEDGE_PROXY_URL } = getServerConfig(); const { KNOWLEDGE_PROXY_URL } = getServerConfig();
export const POST = async (request: Request) => { export const POST = async (request: Request) => {
const params = await request.json(); const params = await request.json();
const fetchRes = await fetch(`${KNOWLEDGE_PROXY_URL}/recreate_vector_store`, { const fetchRes = await fetch(`${KNOWLEDGE_PROXY_URL}/update_docs`, {
body: JSON.stringify(params), body: JSON.stringify(params),
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',

View File

@ -0,0 +1,15 @@
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}/update_info`, {
body: JSON.stringify(params),
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
});
return fetchRes
};

View File

@ -2,19 +2,21 @@ 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;
interface KnowLedgeCardProps { interface KnowLedgeCardProps {
intro: string; intro: string;
name: string; name: string;
vector_store_type?: string;
embed_model?: string;
} }
const KnowledgeCard: React.FC<KnowLedgeCardProps> = (props: KnowLedgeCardProps) => { const KnowledgeCard: React.FC<KnowLedgeCardProps> = (props: KnowLedgeCardProps) => {
const [useFetchKnowledgeDel, useFetchKnowledgeList] = useKnowledgeStore((s) => [
s.useFetchKnowledgeDel, s.useFetchKnowledgeList const [useFetchKnowledgeDel, useFetchKnowledgeList, setEditKnowledge] = useKnowledgeStore((s) => [
s.useFetchKnowledgeDel, s.useFetchKnowledgeList, s.setEditKnowledge
]); ]);
const { mutate } = useFetchKnowledgeList() const { mutate } = useFetchKnowledgeList()
@ -22,6 +24,12 @@ const KnowledgeCard: React.FC<KnowLedgeCardProps> = (props: KnowLedgeCardProps)
const { name, intro } = props; const { name, intro } = props;
const router = useRouter(); const router = useRouter();
const handleCardEditClick = () => { const handleCardEditClick = () => {
setEditKnowledge({
knowledge_base_name: props.name,
kb_info: props.intro,
vector_store_type: props.vector_store_type,
embed_model:props.embed_model,
});
router.push(`/knowledge/${encodeURIComponent(name)}/base`); router.push(`/knowledge/${encodeURIComponent(name)}/base`);
}; };
const delClick = async () => { const delClick = async () => {
@ -33,7 +41,7 @@ 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() mutate()
} }
return Promise.resolve(); return Promise.resolve();

View File

@ -17,7 +17,8 @@ const DesktopPage = memo(() => {
<> <>
<Layout> <Layout>
<KnowledgeCardList /> <KnowledgeCardList />
<FloatButton icon={<Plus />} onClick={() => setShowModal(true)}> <FloatButton
icon={<Plus style={{ width: 20 }} />} onClick={() => setShowModal(true)}>
</FloatButton> </FloatButton>
</Layout> </Layout>

View File

@ -1,22 +1,29 @@
import { InboxOutlined } from '@ant-design/icons'; import { InboxOutlined } from '@ant-design/icons';
import { Form, Modal, Upload, InputNumber, Radio, message } from 'antd'; import { Form, Modal, Upload, InputNumber, Radio, message, Input } from 'antd';
import React, { memo, useState } from 'react'; import React, { memo, useState } from 'react';
import { useKnowledgeStore } from '@/store/knowledge'; import { useKnowledgeStore } from '@/store/knowledge';
import type { GetProp, UploadFile, UploadProps } from 'antd'; import type { GetProp, UploadFile, UploadProps } from 'antd';
import type { KnowledgeUplodDocsParams } from '@/types/knowledge';
type ModalAddFileProps = { type ModalAddFileProps = {
kbName: string; kbName: string;
open: boolean; open: boolean;
setModalOpen: (open: boolean) => void; setModalOpen: (open: boolean) => void;
setSelectedRowKeys: React.Dispatch<React.SetStateAction<string[]>>;
selectedRowKeys: string[];
isRebuildVectorDB?: boolean;
initialValue?: KnowledgeUplodDocsParams;
}; };
type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0]; type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];
const ModalAddFile = memo<ModalAddFileProps>(({ open, setModalOpen, kbName }) => { const ModalAddFile = memo<ModalAddFileProps>(({ open, setModalOpen, setSelectedRowKeys, selectedRowKeys, kbName, initialValue, isRebuildVectorDB }) => {
const [confirmLoading, setConfirmLoading] = useState(false); const [confirmLoading, setConfirmLoading] = useState(false);
const [antdFormInstance] = Form.useForm(); const [antdFormInstance] = Form.useForm();
const [useFetchKnowledgeUploadDocs, useFetchKnowledgeFilesList] = useKnowledgeStore((s) => [ const [useFetchKnowledgeUploadDocs, useFetchKnowledgeFilesList, useFetcReAddVectorDB] = useKnowledgeStore((s) => [
s.useFetchKnowledgeUploadDocs, s.useFetchKnowledgeFilesList s.useFetchKnowledgeUploadDocs, s.useFetchKnowledgeFilesList,
s.useFetcReAddVectorDB
]); ]);
const { mutate } = useFetchKnowledgeFilesList(kbName) const { mutate } = useFetchKnowledgeFilesList(kbName)
const [fileList, setFileList] = useState<UploadFile[]>([]); const [fileList, setFileList] = useState<UploadFile[]>([]);
@ -41,7 +48,23 @@ const ModalAddFile = memo<ModalAddFileProps>(({ open, setModalOpen, kbName }) =>
const fieldsError = await antdFormInstance.validateFields(); const fieldsError = await antdFormInstance.validateFields();
if (fieldsError.length) return; if (fieldsError.length) return;
const values = antdFormInstance.getFieldsValue(true); const values = antdFormInstance.getFieldsValue(true);
if(!fileList.length){
if (isRebuildVectorDB) {
// Re-add to vector library
setConfirmLoading(true);
await useFetcReAddVectorDB({
...values,
"knowledge_base_name": kbName,
"file_names": selectedRowKeys,
}).catch(() => {
message.error(`更新知识库失败`);
})
setConfirmLoading(false);
setSelectedRowKeys([]);
return;
}
if (!fileList.length) {
message.error('请选择文件') message.error('请选择文件')
return; return;
} }
@ -50,13 +73,13 @@ const ModalAddFile = memo<ModalAddFileProps>(({ open, setModalOpen, kbName }) =>
fileList.forEach((file) => { fileList.forEach((file) => {
formData.append('files', file as FileType); formData.append('files', file as FileType);
}); });
for (const key in values) { for (const key in values) {
formData.append(key, values[key]); formData.append(key, values[key]);
} }
formData.append('knowledge_base_name', kbName); formData.append('knowledge_base_name', kbName);
setConfirmLoading(true); setConfirmLoading(true);
const { code: resCode, data: resData, msg: resMsg } = await useFetchKnowledgeUploadDocs(formData) const { code: resCode, msg: resMsg } = await useFetchKnowledgeUploadDocs(formData)
setConfirmLoading(true); setConfirmLoading(true);
if (resCode !== 200) { if (resCode !== 200) {
@ -67,7 +90,7 @@ const ModalAddFile = memo<ModalAddFileProps>(({ open, setModalOpen, kbName }) =>
mutate(); mutate();
setModalOpen(false); setModalOpen(false);
} }
const layout = { const layout = {
labelCol: { span: 10 }, labelCol: { span: 10 },
@ -77,11 +100,12 @@ const ModalAddFile = memo<ModalAddFileProps>(({ open, setModalOpen, kbName }) =>
return ( return (
<Modal <Modal
onCancel={() => setModalOpen(false)} onCancel={() => setModalOpen(false)}
open={open} title="添加文件" open={open}
title={isRebuildVectorDB ? "重新添加至向量库" : "添加文件"}
onOk={onSubmit} onOk={onSubmit}
confirmLoading={confirmLoading} confirmLoading={confirmLoading}
width={600} width={600}
> >
<Form <Form
name="validate_other" name="validate_other"
@ -90,34 +114,36 @@ const ModalAddFile = memo<ModalAddFileProps>(({ open, setModalOpen, kbName }) =>
chunk_size: 0, chunk_size: 0,
chunk_overlap: 0, chunk_overlap: 0,
to_vector_store: true, to_vector_store: true,
...initialValue
}} }}
form={antdFormInstance} 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}> {!isRebuildVectorDB && <>
<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.Group>
<Radio value={true}></Radio> <Radio value={true}></Radio>
<Radio value={false}></Radio> <Radio value={false}></Radio>
</Radio.Group> </Radio.Group>
</Form.Item> </Form.Item>
<Form.Item name="zh_title_enhance" label="开启中文标题加强" {...layout}>
<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.Group>
<Radio value={true}></Radio> <Radio value={true}></Radio>
<Radio value={false}></Radio> <Radio value={false}></Radio>
@ -130,24 +156,16 @@ const ModalAddFile = memo<ModalAddFileProps>(({ open, setModalOpen, kbName }) =>
</Radio.Group> </Radio.Group>
</Form.Item> </Form.Item>
<Form.Item name="chunk_size" label="单段文本最大长度" {...layout} {...layout}>
<Form.Item label="知识库中单段文本最大长度" {...layout} {...layout}> <InputNumber min={0} style={{ width: 200 }} />
<Form.Item name="chunk_size">
<InputNumber min={0} />
</Form.Item>
</Form.Item> </Form.Item>
<Form.Item label="知识库中相邻文本重合长度" {...layout} {...layout}> <Form.Item name="chunk_overlap" label="相邻文本重合长度" {...layout} {...layout}>
<Form.Item name="chunk_overlap"> <InputNumber min={0} style={{ width: 200 }} />
<InputNumber min={0} /> </Form.Item>
</Form.Item> <Form.Item name="docs" label="自定义的docs" {...layout} {...layout}>
<Input style={{ width: 200 }} />
</Form.Item> </Form.Item>
{/* <Form.Item label="docs">
<Form.Item name="docs">
<Input />
</Form.Item>
</Form.Item> */}
</Form> </Form>
</Modal> </Modal>
); );

View File

@ -27,14 +27,15 @@ const App: React.FC<{ params: { id: string } }> = ({ params }) => {
useFetchKnowledgeFilesList, useFetchKnowledgeFilesList,
useFetchKnowledgeDownloadDocs, useFetchKnowledgeDownloadDocs,
useFetcDelInknowledgeDB, useFetcDelInknowledgeDB,
useFetcDelInVectorDB,
useFetcRebuildVectorDB, useFetcRebuildVectorDB,
useFetchKnowledgeDel useFetchKnowledgeDel
] = useKnowledgeStore((s) => [ ] = useKnowledgeStore((s) => [
s.filesData, s.filesData,
s.useFetchKnowledgeFilesList, s.useFetchKnowledgeFilesList,
s.useFetchKnowledgeDownloadDocs, s.useFetchKnowledgeDownloadDocs,
s.useFetcDelInknowledgeDB, s.useFetcDelInknowledgeDB,
s.useFetcDelInVectorDB,
s.useFetcRebuildVectorDB, s.useFetcRebuildVectorDB,
s.useFetchKnowledgeDel s.useFetchKnowledgeDel
]); ]);
@ -42,6 +43,7 @@ const App: React.FC<{ params: { id: string } }> = ({ params }) => {
const [downloadLoading, setDownloadLoading] = useState(false); const [downloadLoading, setDownloadLoading] = useState(false);
const [delDocsLoading, setDelDocsLoading] = useState(false); const [delDocsLoading, setDelDocsLoading] = useState(false);
const [delVSLoading, setDelVSLoading] = useState(false);
const [rebuildVectorDBLoading, setRebuildVectorDBLoading] = useState(false); const [rebuildVectorDBLoading, setRebuildVectorDBLoading] = useState(false);
// rebuild progress // rebuild progress
@ -63,8 +65,8 @@ const App: React.FC<{ params: { id: string } }> = ({ params }) => {
const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]); 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 [isRebuildVectorDB, setIsRebuildVectorDB] = useState(false);
const onSelectChange = (newSelectedRowKeys: string[]) => { const onSelectChange = (newSelectedRowKeys: string[]) => {
console.log('selectedRowKeys changed:', newSelectedRowKeys);
setSelectedRowKeys(newSelectedRowKeys); setSelectedRowKeys(newSelectedRowKeys);
}; };
const columns: TableColumnsType<DataType> = [ const columns: TableColumnsType<DataType> = [
@ -110,10 +112,10 @@ const App: React.FC<{ params: { id: string } }> = ({ params }) => {
setDownloadLoading(false); setDownloadLoading(false);
}; };
const reAddVectorDB = async () => { const reAddVectorDB = async () => {
console.log('reAddShapeDB: ', selectedRowKeys); setIsRebuildVectorDB(true);
setModal(true)
} }
const rebuildVectorDB = async () => { const rebuildVectorDB = async () => {
console.log('rebuildVectorDB ');
setRebuildVectorDBLoading(true); setRebuildVectorDBLoading(true);
try { try {
useFetcRebuildVectorDB({ useFetcRebuildVectorDB({
@ -140,8 +142,16 @@ const App: React.FC<{ params: { id: string } }> = ({ params }) => {
setRebuildVectorDBLoading(false); setRebuildVectorDBLoading(false);
} }
const delInVectorDB = async () => { const delInVectorDB = async () => {
console.log('delInShapeDB: ', selectedRowKeys); setDelVSLoading(true);
await useFetcDelInVectorDB({
"knowledge_base_name": params.id,
"file_names": [...selectedRowKeys],
"delete_content": false, // 不删除文件
"not_refresh_vs_cache": false
}).catch(() => {
message.error(`删除失败`);
})
setDelVSLoading(false);
setSelectedRowKeys([]); setSelectedRowKeys([]);
} }
const delInknowledgeDB = async () => { const delInknowledgeDB = async () => {
@ -149,7 +159,7 @@ const App: React.FC<{ params: { id: string } }> = ({ params }) => {
await useFetcDelInknowledgeDB({ await useFetcDelInknowledgeDB({
"knowledge_base_name": params.id, "knowledge_base_name": params.id,
"file_names": [...selectedRowKeys], "file_names": [...selectedRowKeys],
"delete_content": false, "delete_content": true,
"not_refresh_vs_cache": false "not_refresh_vs_cache": false
}).catch(() => { }).catch(() => {
message.error(`删除失败`); message.error(`删除失败`);
@ -185,7 +195,7 @@ const App: React.FC<{ params: { id: string } }> = ({ params }) => {
<Button disabled={!hasSelected} loading={loading} type="default" onClick={reAddVectorDB}> <Button disabled={!hasSelected} loading={loading} type="default" onClick={reAddVectorDB}>
</Button> </Button>
<Button danger disabled={!hasSelected} loading={loading} type="default" onClick={delInVectorDB} icon={<DeleteOutlined />}> <Button danger disabled={!hasSelected} loading={delVSLoading} type="default" onClick={delInVectorDB} icon={<DeleteOutlined />}>
</Button> </Button>
<Button danger disabled={!hasSelected} loading={delDocsLoading} type="default" onClick={delInknowledgeDB} icon={<DeleteOutlined />}> <Button danger disabled={!hasSelected} loading={delDocsLoading} type="default" onClick={delInknowledgeDB} icon={<DeleteOutlined />}>
@ -196,7 +206,7 @@ const App: React.FC<{ params: { id: string } }> = ({ params }) => {
<Button danger loading={loading} onClick={delKnowledge} type="primary" icon={<DeleteOutlined />}> <Button danger loading={loading} onClick={delKnowledge} type="primary" icon={<DeleteOutlined />}>
</Button> </Button>
<Button loading={loading} onClick={() => setModal(true)} type="primary" icon={<PlusOutlined />}> <Button loading={loading} onClick={() => { setIsRebuildVectorDB(false); setModal(true) }} type="primary" icon={<PlusOutlined />}>
</Button> </Button>
</Flexbox> </Flexbox>
@ -218,7 +228,7 @@ const App: React.FC<{ params: { id: string } }> = ({ params }) => {
/> />
</Spin> </Spin>
</Flexbox > </Flexbox >
<ModalAddFile open={isShowModal} setModalOpen={setModal} kbName={params.id} /> <ModalAddFile open={isShowModal} setModalOpen={setModal} kbName={params.id} selectedRowKeys={selectedRowKeys} setSelectedRowKeys={setSelectedRowKeys} isRebuildVectorDB={isRebuildVectorDB} />
</> </>
); );
}; };

View File

@ -1,61 +1,79 @@
'use client'; 'use client';
import { Form, type ItemGroup } from '@lobehub/ui'; import { Form, type ItemGroup } from '@lobehub/ui';
import { Form as AntForm, Button, Input, InputNumber, Switch } from 'antd'; import { Form as AntForm, Button, Input, InputNumber, Switch, message } from 'antd';
import { Settings } from 'lucide-react'; import { Settings } from 'lucide-react';
import { memo, useCallback } from 'react'; import { memo, useCallback, useState } from 'react';
import { Flexbox } from 'react-layout-kit'; import { Flexbox } from 'react-layout-kit';
import { useKnowledgeStore } from '@/store/knowledge';
import { FORM_STYLE } from '@/const/layoutTokens'; import { FORM_STYLE } from '@/const/layoutTokens';
const KnowledgeBaseConfig = memo(() => { const KnowledgeBaseConfig = memo(({ params }: { params: { id: string } }) => {
const [form] = AntForm.useForm(); const [form] = AntForm.useForm();
const [submitLoading, setSubmitLoading] = useState(false);
const [
editKnowledgeInfo,
useFetchKnowledgeUpdate
] = useKnowledgeStore((s) => [
s.editKnowledgeInfo,
s.useFetchKnowledgeUpdate
]);
// console.log("editKnowledgeInfo===", editKnowledgeInfo);
const handleConfigChange = useCallback(async () => { const handleConfigChange = useCallback(async () => {
try { try {
const values = await form.validateFields(); const values = await form.validateFields();
console.log('Success:', values); // console.log('Success:', values);
setSubmitLoading(true);
const { msg, code } = await useFetchKnowledgeUpdate(values);
if (code === 200) {
message.success(msg);
} else {
message.error(msg);
}
setSubmitLoading(false);
} catch (errorInfo) { } catch (errorInfo) {
console.log('Failed:', errorInfo); console.log('Failed:', errorInfo);
} }
}, [form]); }, [form]);
const system: ItemGroup = { const system: ItemGroup = {
children: [ children: [
{ {
children: <Input placeholder={'请为知识库命名'} />, children: <Input placeholder={'请为知识库命名'} disabled />,
label: '知识库名称', label: '知识库名称',
name: 'name', name: 'knowledge_base_name',
rules: [{ message: '请输入知识库名称', required: true }], rules: [{ message: '请输入知识库名称', required: true }],
}, },
{ {
children: <Input.TextArea placeholder={'请简单介绍你的知识库'} />, children: <Input.TextArea placeholder={'请简单介绍你的知识库'} />,
label: '知识库简介', label: '知识库简介',
name: 'intro', name: 'kb_info',
rules: [{ message: '请输入知识库简介', required: true }], rules: [{ message: '请输入知识库简介', required: true }],
}, },
{ // {
children: <InputNumber placeholder={'请输入数字'} style={{ width: 200 }} />, // children: <InputNumber placeholder={'请输入数字'} style={{ width: 200 }} />,
label: '单段文本最大长度', // label: '单段文本最大长度',
name: 'paragraphMaxLength', // name: 'paragraphMaxLength',
rules: [{ message: '请输入知识库名称', required: true }], // rules: [{ message: '请输入知识库名称', required: true }],
}, // },
{ // {
children: <InputNumber placeholder={'请输入数字'} style={{ width: 200 }} />, // children: <InputNumber placeholder={'请输入数字'} style={{ width: 200 }} />,
label: '相邻文本重合长度', // label: '相邻文本重合长度',
name: 'paragraphOverlapLength', // name: 'paragraphOverlapLength',
rules: [{ message: '请输入知识库名称', required: true }], // rules: [{ message: '请输入知识库名称', required: true }],
}, // },
{ // {
children: <InputNumber style={{ width: 200 }} />, // children: <InputNumber style={{ width: 200 }} />,
label: '文本匹配条数', // label: '文本匹配条数',
name: 'paragraphMatchCount', // name: 'paragraphMatchCount',
rules: [{ message: '请输入知识库名称', required: true }], // rules: [{ message: '请输入知识库名称', required: true }],
}, // },
{ // {
children: <Switch style={{ width: 50 }} />, // children: <Switch style={{ width: 50 }} />,
label: '开启中文标题加强', // label: '开启中文标题加强',
name: 'chineseTitleEnhance', // name: 'chineseTitleEnhance',
}, // },
], ],
icon: Settings, icon: Settings,
title: '知识库设置', title: '知识库设置',
@ -63,9 +81,9 @@ const KnowledgeBaseConfig = memo(() => {
return ( return (
<> <>
<Form form={form} items={[system]} onValuesChange={handleConfigChange} {...FORM_STYLE} /> <Form form={form} items={[system]} initialValues={{...editKnowledgeInfo}} {...FORM_STYLE} />
<Flexbox padding={50}> <Flexbox padding={50}>
<Button size="large" style={{ width: 400 }}> <Button loading={submitLoading} size="large" style={{ width: 400 }} onClick={handleConfigChange} >
</Button> </Button>
</Flexbox> </Flexbox>

View File

@ -2,18 +2,23 @@
import { PropsWithChildren, memo } from 'react'; import { PropsWithChildren, memo } from 'react';
import { Center, Flexbox } from 'react-layout-kit'; import { Center, Flexbox } from 'react-layout-kit';
import AppLayoutDesktop from '@/layout/AppLayout.desktop'; import AppLayoutDesktop from '@/layout/AppLayout.desktop';
import { SidebarTabKey } from '@/store/global/initialState'; import { SidebarTabKey } from '@/store/global/initialState';
import { LeftOutlined } from "@ant-design/icons"
import { Button } from "antd"
import KnowledgeTabs from './tabs'; import KnowledgeTabs from './tabs';
import { useRouter } from 'next/navigation';
interface LayoutProps extends PropsWithChildren { 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);
const router = useRouter();
function goBack(){
router.push('/knowledge')
}
return ( return (
<AppLayoutDesktop sidebarKey={SidebarTabKey.Knowledge}> <AppLayoutDesktop sidebarKey={SidebarTabKey.Knowledge}>
<Flexbox direction="horizontal" flex={1} gap={40} height={'100%'}> <Flexbox direction="horizontal" flex={1} gap={40} height={'100%'}>
@ -24,8 +29,10 @@ export default memo<LayoutProps>(({ children, params }) => {
style={{ borderInlineEnd: '1px solid #333333' }} style={{ borderInlineEnd: '1px solid #333333' }}
> >
<Flexbox padding={10}> <Flexbox padding={10}>
<Center></Center> <Center>
<Center></Center> <Button onClick={goBack} type="link" icon={<LeftOutlined />}>{params.id}</Button>
</Center>
{/* <Center>{params.id}</Center> */}
</Flexbox> </Flexbox>
<KnowledgeTabs params={params} /> <KnowledgeTabs params={params} />

View File

@ -48,12 +48,14 @@ export const API_ENDPOINTS = mapWithBasePath({
// knowledge // knowledge
knowledgeList: '/api/knowledge/list', knowledgeList: '/api/knowledge/list',
knowledgeAdd: '/api/knowledge/add', knowledgeAdd: '/api/knowledge/add',
knowledgeUpdate: '/api/knowledge/update',
knowledgeDel: '/api/knowledge/del', knowledgeDel: '/api/knowledge/del',
// knowledge files // knowledge files
knowledgeFilesList: '/api/knowledge/listFiles', knowledgeFilesList: '/api/knowledge/listFiles',
knowledgeUploadDocs: '/api/knowledge/uploadDocs', knowledgeUploadDocs: '/api/knowledge/uploadDocs',
knowledgeDownloadDocs: '/api/knowledge/downloadDocs', knowledgeDownloadDocs: '/api/knowledge/downloadDocs',
knowledgeDelInknowledgeDB: '/api/knowledge/deleteDocs', knowledgeDelInknowledgeDB: '/api/knowledge/deleteDocs',
knowledgeDelVectorDB:'/api/knowledge/delVectorDocs',
knowledgeRebuildVectorDB: '/api/knowledge/rebuildVectorDB', knowledgeRebuildVectorDB: '/api/knowledge/rebuildVectorDB',
knowledgeReAddVectorDB: '/api/knowledge/reAddVectorDB', knowledgeReAddVectorDB: '/api/knowledge/reAddVectorDB',

View File

@ -2,12 +2,14 @@
import type { import type {
KnowledgeList, KnowledgeFormFields, Reseponse, KnowledgeList, KnowledgeFormFields, Reseponse,
KnowledgeFilesList, KnowledgeDelDocsParams, KnowledgeDelDocsRes, KnowledgeFilesList, KnowledgeDelDocsParams, KnowledgeDelDocsRes,
KnowledgeRebuildVectorParams, KnowledgeRebuildVectorRes KnowledgeRebuildVectorParams,
ReAddVectorDBParams, ReAddVectorDBRes,
KnowledgeUplodDocsParams, KnowledgeUplodDocsRes
} from '@/types/knowledge'; } from '@/types/knowledge';
import { fetchSSE, FetchSSEOptions } from '@/utils/fetch'; 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}`);
@ -25,6 +27,16 @@ class KnowledgeService {
}); });
return res.json(); return res.json();
}; };
update = async (formValues: Partial<KnowledgeFormFields>) => {
const res = await fetch(`${API_ENDPOINTS.knowledgeUpdate}`, {
body: JSON.stringify(formValues),
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
});
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}`, {
@ -69,11 +81,11 @@ class KnowledgeService {
return res.json(); return res.json();
}; };
rebuildVectorDB = async (params: KnowledgeRebuildVectorParams, opts: rebuildVectorDB = async (params: KnowledgeRebuildVectorParams, opts:
{ onFinish: FetchSSEOptions["onFinish"]; onMessageHandle: FetchSSEOptions["onMessageHandle"] } { onFinish: FetchSSEOptions["onFinish"]; onMessageHandle: FetchSSEOptions["onMessageHandle"] }
) => { ) => {
const { onFinish, onMessageHandle } = opts; const { onFinish, onMessageHandle } = opts;
fetchSSE(async ()=> await fetch(`${API_ENDPOINTS.knowledgeRebuildVectorDB}`, { fetchSSE(async () => await fetch(`${API_ENDPOINTS.knowledgeRebuildVectorDB}`, {
body: JSON.stringify({ body: JSON.stringify({
...params, ...params,
}), }),
@ -90,16 +102,18 @@ class KnowledgeService {
}) })
}; };
// delVectorDocs = async (formData: FormData): Promise<Reseponse<{}>> => { delVectorDocs = async (params: KnowledgeDelDocsParams): Promise<Reseponse<KnowledgeDelDocsRes>> => {
// // const res = await fetch(`${API_ENDPOINTS.knowledgeUploadDocs}`, { const res = await fetch(`${API_ENDPOINTS.knowledgeDelVectorDB}`, {
// // body: formData, body: JSON.stringify({
// // // headers: { ...params,
// // // 'Content-Type': 'application/json', }),
// // // }, headers: {
// // method: 'POST', 'Content-Type': 'application/json',
// // }); },
// // return res.json(); method: 'POST',
// }; });
return res.json();
};
downloadDocs = async (kbName: string, docName: string): Promise<Reseponse<{}>> => { downloadDocs = async (kbName: string, docName: string): Promise<Reseponse<{}>> => {
const queryString = new URLSearchParams({ const queryString = new URLSearchParams({
@ -111,19 +125,20 @@ class KnowledgeService {
console.log('res', res) console.log('res', res)
const data = await res.json(); const data = await res.json();
return data; return data;
};
reAddVectorDB = async (params: ReAddVectorDBParams): Promise<Reseponse<ReAddVectorDBRes>> => {
const res = await fetch(`${API_ENDPOINTS.knowledgeReAddVectorDB}`, {
body: JSON.stringify({
...params,
}),
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
});
return res.json();
}; };
// 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();
// };
} }

View File

@ -1,24 +1,30 @@
import useSWR, { SWRResponse } from 'swr'; import useSWR, { SWRResponse } from 'swr';
import type { StateCreator } from 'zustand/vanilla'; 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 {
import type {
KnowledgeFormFields, KnowledgeList, Reseponse, KnowledgeFilesList, KnowledgeFormFields, KnowledgeList, Reseponse, KnowledgeFilesList,
KnowledgeDelDocsParams, KnowledgeDelDocsRes, KnowledgeDelDocsParams, KnowledgeDelDocsRes,
KnowledgeRebuildVectorParams, KnowledgeRebuildVectorRes KnowledgeRebuildVectorParams, KnowledgeUplodDocsParams, KnowledgeUplodDocsRes,
ReAddVectorDBParams, ReAddVectorDBRes,
} from '@/types/knowledge'; } from '@/types/knowledge';
import type { FetchSSEOptions } from '@/utils/fetch'; import type { FetchSSEOptions } from '@/utils/fetch';
import type { Store } from './store'; import type { Store } from './store';
export interface StoreAction { export interface StoreAction {
// 知识库数据列表
listData: KnowledgeList; listData: KnowledgeList;
// 当前编辑的知识库
editKnowledgeInfo: null | KnowledgeFormFields;
setEditKnowledge: (data: KnowledgeFormFields) => void;
useFetchKnowledgeList: () => SWRResponse<Reseponse<KnowledgeList>>; useFetchKnowledgeList: () => SWRResponse<Reseponse<KnowledgeList>>;
useFetchKnowledgeAdd: (arg: KnowledgeFormFields) => Promise<Reseponse<KnowledgeFormFields>>; useFetchKnowledgeAdd: (arg: KnowledgeFormFields) => Promise<Reseponse<KnowledgeFormFields>>;
useFetchKnowledgeUpdate: (arg: Partial<KnowledgeFormFields>) => Promise<Reseponse<KnowledgeFormFields>>;
useFetchKnowledgeDel: (name: string) => Promise<Reseponse<{}>>; useFetchKnowledgeDel: (name: string) => Promise<Reseponse<{}>>;
// files // files
@ -27,11 +33,12 @@ export interface StoreAction {
useFetchKnowledgeUploadDocs: (arg: FormData) => Promise<Reseponse<{}>>; useFetchKnowledgeUploadDocs: (arg: FormData) => Promise<Reseponse<{}>>;
useFetchKnowledgeDownloadDocs: (kbName: string, docName: string) => Promise<Reseponse<{}>>; useFetchKnowledgeDownloadDocs: (kbName: string, docName: string) => Promise<Reseponse<{}>>;
useFetcDelInknowledgeDB: (arg: KnowledgeDelDocsParams) => Promise<Reseponse<KnowledgeDelDocsRes>>; useFetcDelInknowledgeDB: (arg: KnowledgeDelDocsParams) => Promise<Reseponse<KnowledgeDelDocsRes>>;
useFetcRebuildVectorDB: (arg: KnowledgeRebuildVectorParams, options: { useFetcDelInVectorDB: (arg: KnowledgeDelDocsParams) => Promise<Reseponse<KnowledgeDelDocsRes>>;
onFinish: FetchSSEOptions["onFinish"]; useFetcRebuildVectorDB: (arg: KnowledgeRebuildVectorParams, options: {
onMessageHandle: FetchSSEOptions["onMessageHandle"] onFinish: FetchSSEOptions["onFinish"];
onMessageHandle: FetchSSEOptions["onMessageHandle"]
}) => void; }) => void;
useFetcReAddVectorDB: (arg: ReAddVectorDBParams) => Promise<Reseponse<ReAddVectorDBRes>>;
} }
export const createKnowledgeAction: StateCreator< export const createKnowledgeAction: StateCreator<
@ -55,11 +62,12 @@ export const createKnowledgeAction: StateCreator<
useFetchKnowledgeAdd: async (formValues) => { useFetchKnowledgeAdd: async (formValues) => {
return await knowledgeService.add(formValues) return await knowledgeService.add(formValues)
}, },
useFetchKnowledgeUpdate: async (formValues) => {
return await knowledgeService.update(formValues)
},
useFetchKnowledgeDel: async (name) => { useFetchKnowledgeDel: async (name) => {
return await knowledgeService.del(name) return await knowledgeService.del(name)
}, },
filesData: [], filesData: [],
useFetchKnowledgeFilesList: (knowledge_base_name) => { useFetchKnowledgeFilesList: (knowledge_base_name) => {
return useSWR<Reseponse<KnowledgeFilesList>>( return useSWR<Reseponse<KnowledgeFilesList>>(
@ -81,8 +89,20 @@ export const createKnowledgeAction: StateCreator<
useFetcDelInknowledgeDB: (params) => { useFetcDelInknowledgeDB: (params) => {
return knowledgeService.delInknowledgeDB(params); return knowledgeService.delInknowledgeDB(params);
}, },
useFetcDelInVectorDB: async (name) => {
return await knowledgeService.delVectorDocs(name)
},
useFetcRebuildVectorDB: (params, options) => { useFetcRebuildVectorDB: (params, options) => {
return knowledgeService.rebuildVectorDB(params, options); return knowledgeService.rebuildVectorDB(params, options);
},
useFetcReAddVectorDB: (params) => {
return knowledgeService.reAddVectorDB(params);
},
editKnowledgeInfo: null,
setEditKnowledge: (data) => {
set({ editKnowledgeInfo: data })
} }
}); });

View File

@ -4,9 +4,9 @@ export interface Reseponse<T> { code: number; msg: string; data: T }
// create Knowledge fields // 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;
kb_info?: string; kb_info?: string;
embed_model: string; embed_model?: string;
} }
// Knowledge base list // Knowledge base list
@ -32,14 +32,37 @@ export interface KnowledgeDelDocsParams {
delete_content: boolean; delete_content: boolean;
not_refresh_vs_cache: boolean; not_refresh_vs_cache: boolean;
} }
export interface KnowledgeDelDocsRes { export interface KnowledgeDelDocsRes {}
knowledge_base_name: string;
file_names: string[];
delete_content: boolean;
not_refresh_vs_cache: boolean;
}
// upload docs
export interface KnowledgeUplodDocsParams {
knowledge_base_name: string;
files: File[];
override?: boolean;
to_vector_store?: string;
chunk_size?: string;
chunk_overlap?: string;
zh_title_enhance?: string;
docs?: string;
docsnot_refresh_vs_cache?: string;
}
export interface KnowledgeUplodDocsRes { }
// re add docs
export interface ReAddVectorDBParams {
"knowledge_base_name": string,
"file_names":string[];
"chunk_size": number;
"chunk_overlap": number;
"zh_title_enhance": boolean;
"override_custom_docs": boolean;
"docs": string;
"not_refresh_vs_cache": boolean
}
export interface ReAddVectorDBRes { }
// Rebuild the vector library // Rebuild the vector library
export interface KnowledgeRebuildVectorParams { export interface KnowledgeRebuildVectorParams {