mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-11 21:30:59 +00:00
feat: rag fe framework
This commit is contained in:
@@ -130,7 +130,6 @@ export default function BotDetailDialog({
|
|||||||
onFormCancel={handleFormCancel}
|
onFormCancel={handleFormCancel}
|
||||||
onBotDeleted={handleBotDeleted}
|
onBotDeleted={handleBotDeleted}
|
||||||
onNewBotCreated={handleNewBotCreated}
|
onNewBotCreated={handleNewBotCreated}
|
||||||
hideButtons={true}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter className="px-6 py-4 border-t shrink-0">
|
<DialogFooter className="px-6 py-4 border-t shrink-0">
|
||||||
@@ -202,7 +201,6 @@ export default function BotDetailDialog({
|
|||||||
onFormCancel={handleFormCancel}
|
onFormCancel={handleFormCancel}
|
||||||
onBotDeleted={handleBotDeleted}
|
onBotDeleted={handleBotDeleted}
|
||||||
onNewBotCreated={handleNewBotCreated}
|
onNewBotCreated={handleNewBotCreated}
|
||||||
hideButtons={true}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{activeMenu === 'logs' && botId && (
|
{activeMenu === 'logs' && botId && (
|
||||||
|
|||||||
@@ -67,14 +67,12 @@ export default function BotForm({
|
|||||||
onFormCancel,
|
onFormCancel,
|
||||||
onBotDeleted,
|
onBotDeleted,
|
||||||
onNewBotCreated,
|
onNewBotCreated,
|
||||||
hideButtons = false,
|
|
||||||
}: {
|
}: {
|
||||||
initBotId?: string;
|
initBotId?: string;
|
||||||
onFormSubmit: (value: z.infer<ReturnType<typeof getFormSchema>>) => void;
|
onFormSubmit: (value: z.infer<ReturnType<typeof getFormSchema>>) => void;
|
||||||
onFormCancel: () => void;
|
onFormCancel: () => void;
|
||||||
onBotDeleted: () => void;
|
onBotDeleted: () => void;
|
||||||
onNewBotCreated: (botId: string) => void;
|
onNewBotCreated: (botId: string) => void;
|
||||||
hideButtons?: boolean;
|
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const formSchema = getFormSchema(t);
|
const formSchema = getFormSchema(t);
|
||||||
@@ -527,45 +525,6 @@ export default function BotForm({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!hideButtons && (
|
|
||||||
<div className="sticky bottom-0 left-0 right-0 bg-background border-t p-4 mt-4">
|
|
||||||
<div className="flex justify-end gap-2">
|
|
||||||
{!initBotId && (
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
onClick={form.handleSubmit(onDynamicFormSubmit)}
|
|
||||||
>
|
|
||||||
{t('common.submit')}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{initBotId && (
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="destructive"
|
|
||||||
onClick={() => setShowDeleteConfirmModal(true)}
|
|
||||||
>
|
|
||||||
{t('common.delete')}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
onClick={form.handleSubmit(onDynamicFormSubmit)}
|
|
||||||
>
|
|
||||||
{t('common.save')}
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
onClick={() => onFormCancel()}
|
|
||||||
>
|
|
||||||
{t('common.cancel')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export default function BotConfigPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.configPageContainer}>
|
<div>
|
||||||
<BotDetailDialog
|
<BotDetailDialog
|
||||||
open={detailDialogOpen}
|
open={detailDialogOpen}
|
||||||
onOpenChange={setDetailDialogOpen}
|
onOpenChange={setDetailDialogOpen}
|
||||||
|
|||||||
@@ -8,16 +8,28 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogFooter,
|
DialogFooter,
|
||||||
} from '@/components/ui/dialog';
|
} from '@/components/ui/dialog';
|
||||||
|
import {
|
||||||
|
Sidebar,
|
||||||
|
SidebarContent,
|
||||||
|
SidebarGroup,
|
||||||
|
SidebarGroupContent,
|
||||||
|
SidebarMenu,
|
||||||
|
SidebarMenuButton,
|
||||||
|
SidebarMenuItem,
|
||||||
|
SidebarProvider,
|
||||||
|
} from '@/components/ui/sidebar';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { httpClient } from '@/app/infra/http/HttpClient';
|
// import { httpClient } from '@/app/infra/http/HttpClient';
|
||||||
import { KnowledgeBase } from '@/app/infra/entities/api';
|
// import { KnowledgeBase } from '@/app/infra/entities/api';
|
||||||
|
import KBForm from '@/app/home/knowledge/components/kb-form/KBForm';
|
||||||
|
|
||||||
interface KBDetailDialogProps {
|
interface KBDetailDialogProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
kbId?: string;
|
kbId?: string;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
onFormSubmit: (value: z.infer<any>) => void;
|
onFormSubmit: (value: z.infer<any>) => void;
|
||||||
onFormCancel: () => void;
|
onFormCancel: () => void;
|
||||||
onKbDeleted: () => void;
|
onKbDeleted: () => void;
|
||||||
@@ -36,7 +48,7 @@ export default function KBDetailDialog({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [kbId, setKbId] = useState<string | undefined>(propKbId);
|
const [kbId, setKbId] = useState<string | undefined>(propKbId);
|
||||||
const [activeMenu, setActiveMenu] = useState('metadata');
|
const [activeMenu, setActiveMenu] = useState('metadata');
|
||||||
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
// const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setKbId(propKbId);
|
setKbId(propKbId);
|
||||||
@@ -58,8 +70,8 @@ export default function KBDetailDialog({
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'files',
|
key: 'documents',
|
||||||
label: t('knowledge.files'),
|
label: t('knowledge.documents'),
|
||||||
icon: (
|
icon: (
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -79,11 +91,121 @@ export default function KBDetailDialog({
|
|||||||
<DialogContent className="overflow-hidden p-0 !max-w-[40vw] max-h-[70vh] flex">
|
<DialogContent className="overflow-hidden p-0 !max-w-[40vw] max-h-[70vh] flex">
|
||||||
<main className="flex flex-1 flex-col h-[70vh]">
|
<main className="flex flex-1 flex-col h-[70vh]">
|
||||||
<DialogHeader className="px-6 pt-6 pb-4 shrink-0">
|
<DialogHeader className="px-6 pt-6 pb-4 shrink-0">
|
||||||
<DialogTitle>{t('knowledge.newKb')}</DialogTitle>
|
<DialogTitle>{t('knowledge.createKnowledgeBase')}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
<div className="flex-1 overflow-y-auto px-6 pb-6">
|
||||||
|
{activeMenu === 'metadata' && (
|
||||||
|
<KBForm
|
||||||
|
initKbId={undefined}
|
||||||
|
onFormSubmit={onFormSubmit}
|
||||||
|
onFormCancel={onFormCancel}
|
||||||
|
onKbDeleted={onKbDeleted}
|
||||||
|
onNewKbCreated={onNewKbCreated}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{activeMenu === 'documents' && <div>documents</div>}
|
||||||
|
</div>
|
||||||
|
{activeMenu === 'metadata' && (
|
||||||
|
<DialogFooter className="px-6 py-4 border-t shrink-0">
|
||||||
|
<div className="flex justify-end gap-2">
|
||||||
|
<Button type="submit" form="kb-form">
|
||||||
|
{t('common.save')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
onClick={onFormCancel}
|
||||||
|
>
|
||||||
|
{t('common.cancel')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</DialogFooter>
|
||||||
|
)}
|
||||||
</main>
|
</main>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
|
<DialogContent className="overflow-hidden p-0 !max-w-[50rem] max-h-[75vh] flex">
|
||||||
|
<SidebarProvider className="items-start w-full flex">
|
||||||
|
<Sidebar
|
||||||
|
collapsible="none"
|
||||||
|
className="hidden md:flex h-[80vh] w-40 min-w-[120px] border-r bg-white"
|
||||||
|
>
|
||||||
|
<SidebarContent>
|
||||||
|
<SidebarGroup>
|
||||||
|
<SidebarGroupContent>
|
||||||
|
<SidebarMenu>
|
||||||
|
{menu.map((item) => (
|
||||||
|
<SidebarMenuItem key={item.key}>
|
||||||
|
<SidebarMenuButton
|
||||||
|
asChild
|
||||||
|
isActive={activeMenu === item.key}
|
||||||
|
onClick={() => setActiveMenu(item.key)}
|
||||||
|
>
|
||||||
|
<a href="#">
|
||||||
|
{item.icon}
|
||||||
|
<span>{item.label}</span>
|
||||||
|
</a>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
))}
|
||||||
|
</SidebarMenu>
|
||||||
|
</SidebarGroupContent>
|
||||||
|
</SidebarGroup>
|
||||||
|
</SidebarContent>
|
||||||
|
</Sidebar>
|
||||||
|
<main className="flex flex-1 flex-col h-[75vh]">
|
||||||
|
<DialogHeader className="px-6 pt-6 pb-4 shrink-0">
|
||||||
|
<DialogTitle>
|
||||||
|
{activeMenu === 'metadata'
|
||||||
|
? t('knowledge.createKnowledgeBase')
|
||||||
|
: t('knowledge.editDocument')}
|
||||||
|
</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="flex-1 overflow-y-auto px-6 pb-6">
|
||||||
|
{activeMenu === 'metadata' && (
|
||||||
|
<KBForm
|
||||||
|
initKbId={kbId}
|
||||||
|
onFormSubmit={onFormSubmit}
|
||||||
|
onFormCancel={onFormCancel}
|
||||||
|
onKbDeleted={onKbDeleted}
|
||||||
|
onNewKbCreated={onNewKbCreated}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{activeMenu === 'documents' && <div>documents</div>}
|
||||||
|
</div>
|
||||||
|
{activeMenu === 'metadata' && (
|
||||||
|
<DialogFooter className="px-6 py-4 border-t shrink-0">
|
||||||
|
<div className="flex justify-end gap-2">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="destructive"
|
||||||
|
onClick={onKbDeleted}
|
||||||
|
>
|
||||||
|
{t('common.delete')}
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" form="kb-form">
|
||||||
|
{t('common.save')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
onClick={onFormCancel}
|
||||||
|
>
|
||||||
|
{t('common.cancel')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</DialogFooter>
|
||||||
|
)}
|
||||||
|
</main>
|
||||||
|
</SidebarProvider>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export default function KBCard({ kbCardVO }: { kbCardVO: KnowledgeBaseVO }) {
|
|||||||
<path d="M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM13 12H17V14H11V7H13V12Z"></path>
|
<path d="M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM13 12H17V14H11V7H13V12Z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
<div className={`${styles.basicInfoUpdateTimeText}`}>
|
<div className={`${styles.basicInfoUpdateTimeText}`}>
|
||||||
{t('knowledge.bases.updateTime')}
|
{t('knowledge.updateTime')}
|
||||||
{kbCardVO.lastUpdatedTimeAgo}
|
{kbCardVO.lastUpdatedTimeAgo}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export interface IEmbeddingModelEntity {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
FormDescription,
|
||||||
|
} from '@/components/ui/form';
|
||||||
|
import { IEmbeddingModelEntity } from './ChooseEntity';
|
||||||
|
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
|
||||||
|
const getFormSchema = (t: (key: string) => string) =>
|
||||||
|
z.object({
|
||||||
|
name: z.string().min(1, { message: t('knowledge.kbNameRequired') }),
|
||||||
|
description: z
|
||||||
|
.string()
|
||||||
|
.min(1, { message: t('knowledge.kbDescriptionRequired') }),
|
||||||
|
embeddingModelUUID: z
|
||||||
|
.string()
|
||||||
|
.min(1, { message: t('knowledge.embeddingModelUUIDRequired') }),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function KBForm({
|
||||||
|
initKbId,
|
||||||
|
onFormSubmit,
|
||||||
|
onFormCancel,
|
||||||
|
onKbDeleted,
|
||||||
|
onNewKbCreated,
|
||||||
|
}: {
|
||||||
|
initKbId?: string;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
onFormSubmit: (value: any) => void;
|
||||||
|
onFormCancel: () => void;
|
||||||
|
onKbDeleted: () => void;
|
||||||
|
onNewKbCreated: (kbId: string) => void;
|
||||||
|
}) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const formSchema = getFormSchema(t);
|
||||||
|
|
||||||
|
const form = useForm<z.infer<typeof formSchema>>({
|
||||||
|
resolver: zodResolver(formSchema),
|
||||||
|
defaultValues: {
|
||||||
|
name: '',
|
||||||
|
description: t('knowledge.defaultDescription'),
|
||||||
|
embeddingModelUUID: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [embeddingModelNameList, setEmbeddingModelNameList] = useState<
|
||||||
|
IEmbeddingModelEntity[]
|
||||||
|
>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getEmbeddingModelNameList();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getEmbeddingModelNameList = async () => {
|
||||||
|
const resp = await httpClient.getProviderEmbeddingModels();
|
||||||
|
setEmbeddingModelNameList(
|
||||||
|
resp.models.map((item) => {
|
||||||
|
return {
|
||||||
|
label: item.name,
|
||||||
|
value: item.uuid,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Form {...form}>
|
||||||
|
<form
|
||||||
|
onSubmit={form.handleSubmit(onFormSubmit)}
|
||||||
|
id="kb-form"
|
||||||
|
className="space-y-8"
|
||||||
|
>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="name"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t('knowledge.kbName')}
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="description"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t('knowledge.kbDescription')}
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="embeddingModelUUID"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t('knowledge.embeddingModelUUID')}
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<div className="relative">
|
||||||
|
<Select
|
||||||
|
onValueChange={(value) => {
|
||||||
|
field.onChange(value);
|
||||||
|
console.log('value', value);
|
||||||
|
}}
|
||||||
|
value={field.value}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue
|
||||||
|
placeholder={t('knowledge.selectEmbeddingModel')}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent className="fixed z-[1000]">
|
||||||
|
<SelectGroup>
|
||||||
|
{embeddingModelNameList.map((item) => (
|
||||||
|
<SelectItem key={item.value} value={item.value}>
|
||||||
|
{item.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t('knowledge.embeddingModelDescription')}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -3,32 +3,102 @@
|
|||||||
import CreateCardComponent from '@/app/infra/basic-component/create-card-component/CreateCardComponent';
|
import CreateCardComponent from '@/app/infra/basic-component/create-card-component/CreateCardComponent';
|
||||||
import styles from './knowledgeBase.module.css';
|
import styles from './knowledgeBase.module.css';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { KnowledgeBaseVO } from '@/app/home/knowledge/components/kb-card/KBCardVO';
|
import { KnowledgeBaseVO } from '@/app/home/knowledge/components/kb-card/KBCardVO';
|
||||||
import KBCard from '@/app/home/knowledge/components/kb-card/KBCard';
|
import KBCard from '@/app/home/knowledge/components/kb-card/KBCard';
|
||||||
|
import KBDetailDialog from '@/app/home/knowledge/KBDetailDialog';
|
||||||
|
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||||
|
import { KnowledgeBase } from '@/app/infra/entities/api';
|
||||||
|
|
||||||
export default function KnowledgePage() {
|
export default function KnowledgePage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [knowledgeBaseList, setKnowledgeBaseList] = useState<KnowledgeBaseVO[]>(
|
const [knowledgeBaseList, setKnowledgeBaseList] = useState<KnowledgeBaseVO[]>(
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
const [selectedKbId, setSelectedKbId] = useState<string>('');
|
||||||
|
const [detailDialogOpen, setDetailDialogOpen] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getKnowledgeBaseList();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function getKnowledgeBaseList() {
|
||||||
|
const resp = await httpClient.getKnowledgeBases();
|
||||||
|
setKnowledgeBaseList(
|
||||||
|
resp.bases.map((kb: KnowledgeBase) => {
|
||||||
|
const currentTime = new Date();
|
||||||
|
const lastUpdatedTimeAgo = Math.floor(
|
||||||
|
(currentTime.getTime() -
|
||||||
|
new Date(kb.updated_at ?? currentTime.getTime()).getTime()) /
|
||||||
|
1000 /
|
||||||
|
60 /
|
||||||
|
60 /
|
||||||
|
24,
|
||||||
|
);
|
||||||
|
|
||||||
|
const lastUpdatedTimeAgoText =
|
||||||
|
lastUpdatedTimeAgo > 0
|
||||||
|
? ` ${lastUpdatedTimeAgo} ${t('knowledge.daysAgo')}`
|
||||||
|
: t('knowledge.today');
|
||||||
|
|
||||||
|
return new KnowledgeBaseVO({
|
||||||
|
id: kb.uuid || '',
|
||||||
|
name: kb.name,
|
||||||
|
description: kb.description,
|
||||||
|
embeddingModelUUID: kb.embedding_model_uuid,
|
||||||
|
lastUpdatedTimeAgo: lastUpdatedTimeAgoText,
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const handleKBCardClick = (kbId: string) => {
|
const handleKBCardClick = (kbId: string) => {
|
||||||
// setIsEditForm(false);
|
setSelectedKbId(kbId);
|
||||||
// setModalOpen(true);
|
setDetailDialogOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCreateKBClick = () => {
|
||||||
|
setSelectedKbId('');
|
||||||
|
setDetailDialogOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const handleFormSubmit = (value: any) => {
|
||||||
|
console.log('handleFormSubmit', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFormCancel = () => {
|
||||||
|
setDetailDialogOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKbDeleted = () => {
|
||||||
|
getKnowledgeBaseList();
|
||||||
|
setDetailDialogOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNewKbCreated = () => {
|
||||||
|
getKnowledgeBaseList();
|
||||||
|
setDetailDialogOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<KBDetailDialog
|
||||||
|
open={detailDialogOpen}
|
||||||
|
onOpenChange={setDetailDialogOpen}
|
||||||
|
kbId={selectedKbId || undefined}
|
||||||
|
onFormSubmit={handleFormSubmit}
|
||||||
|
onFormCancel={handleFormCancel}
|
||||||
|
onKbDeleted={handleKbDeleted}
|
||||||
|
onNewKbCreated={handleNewKbCreated}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className={styles.knowledgeListContainer}>
|
<div className={styles.knowledgeListContainer}>
|
||||||
<CreateCardComponent
|
<CreateCardComponent
|
||||||
width={'100%'}
|
width={'100%'}
|
||||||
height={'10rem'}
|
height={'10rem'}
|
||||||
plusSize={'90px'}
|
plusSize={'90px'}
|
||||||
onClick={() => {
|
onClick={handleCreateKBClick}
|
||||||
// setIsEditForm(false);
|
|
||||||
// setModalOpen(true);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{knowledgeBaseList.map((kb) => {
|
{knowledgeBaseList.map((kb) => {
|
||||||
|
|||||||
@@ -232,9 +232,23 @@ const enUS = {
|
|||||||
},
|
},
|
||||||
knowledge: {
|
knowledge: {
|
||||||
title: 'Knowledge',
|
title: 'Knowledge',
|
||||||
|
createKnowledgeBase: 'Create Knowledge Base',
|
||||||
description: 'Configuring knowledge bases for improved LLM responses',
|
description: 'Configuring knowledge bases for improved LLM responses',
|
||||||
metadata: 'Metadata',
|
metadata: 'Metadata',
|
||||||
files: 'Files',
|
documents: 'Documents',
|
||||||
|
kbNameRequired: 'Knowledge base name cannot be empty',
|
||||||
|
kbDescriptionRequired: 'Knowledge base description cannot be empty',
|
||||||
|
embeddingModelUUIDRequired: 'Embedding model cannot be empty',
|
||||||
|
daysAgo: 'days ago',
|
||||||
|
today: 'Today',
|
||||||
|
kbName: 'Knowledge Base Name',
|
||||||
|
kbDescription: 'Knowledge Base Description',
|
||||||
|
defaultDescription: 'A knowledge base',
|
||||||
|
embeddingModelUUID: 'Embedding Model',
|
||||||
|
selectEmbeddingModel: 'Select Embedding Model',
|
||||||
|
embeddingModelDescription:
|
||||||
|
'Used to vectorize the text, you can configure it in the Models page',
|
||||||
|
updateTime: 'Updated ',
|
||||||
},
|
},
|
||||||
register: {
|
register: {
|
||||||
title: 'Initialize LangBot 👋',
|
title: 'Initialize LangBot 👋',
|
||||||
|
|||||||
Reference in New Issue
Block a user