Feat: Rendering recall test page #3221 (#7689)

### What problem does this PR solve?

Feat: Rendering recall test page #3221
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-05-16 18:56:48 +08:00
committed by GitHub
parent d73a08b9eb
commit bfaa469b9a
10 changed files with 199 additions and 134 deletions

View File

@ -50,7 +50,8 @@ const MarkdownContent = ({
const { setDocumentIds, data: fileThumbnails } =
useFetchDocumentThumbnailsByIds();
const contentWithCursor = useMemo(() => {
let text = DOMPurify.sanitize(content);
// let text = DOMPurify.sanitize(content);
let text = content;
if (text === '') {
text = t('chat.searching');
}

View File

@ -0,0 +1,15 @@
import { ReactNode } from 'react';
type TopTitleProps = {
title: ReactNode;
description: ReactNode;
};
export function TopTitle({ title, description }: TopTitleProps) {
return (
<div className="pb-5">
<div className="text-2xl font-semibold">{title}</div>
<p className="text-text-sub-title pt-2">{description}</p>
</div>
);
}

View File

@ -5,6 +5,7 @@ import { DocumentParserType } from '@/constants/knowledge';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm, useWatch } from 'react-hook-form';
import { z } from 'zod';
import { TopTitle } from '../dataset-title';
import CategoryPanel from './category-panel';
import { ChunkMethodForm } from './chunk-method-form';
import { formSchema } from './form-schema';
@ -74,13 +75,11 @@ export default function DatasetSettings() {
return (
<section className="p-5 ">
<div className="pb-5">
<div className="text-2xl font-semibold">Configuration</div>
<p className="text-text-sub-title pt-2">
Update your knowledge base configuration here, particularly the chunk
method.
</p>
</div>
<TopTitle
title={'Configuration'}
description={` Update your knowledge base configuration here, particularly the chunk
method.`}
></TopTitle>
<div className="flex gap-14">
<Form {...form}>
<form

View File

@ -1,8 +1,16 @@
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { FormContainer } from '@/components/form-container';
import { FilterButton } from '@/components/list-filter-bar';
import { FilterPopover } from '@/components/list-filter-bar/filter-popover';
import { FilterCollection } from '@/components/list-filter-bar/interface';
import { Button } from '@/components/ui/button';
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
import { useTranslate } from '@/hooks/common-hooks';
import { useTestRetrieval } from '@/hooks/use-knowledge-request';
import { ITestingChunk } from '@/interfaces/database/knowledge';
import { camelCase } from 'lodash';
import { Plus } from 'lucide-react';
import { useMemo } from 'react';
import { TopTitle } from '../dataset-title';
import TestingForm from './testing-form';
const similarityList: Array<{ field: keyof ITestingChunk; label: string }> = [
@ -14,7 +22,7 @@ const similarityList: Array<{ field: keyof ITestingChunk; label: string }> = [
const ChunkTitle = ({ item }: { item: ITestingChunk }) => {
const { t } = useTranslate('knowledgeDetails');
return (
<div className="flex gap-3 text-xs">
<div className="flex gap-3 text-xs text-text-sub-title-invert italic">
{similarityList.map((x) => (
<div key={x.field} className="space-x-1">
<span>{((item[x.field] as number) * 100).toFixed(2)}</span>
@ -26,43 +34,83 @@ const ChunkTitle = ({ item }: { item: ITestingChunk }) => {
};
export default function RetrievalTesting() {
const { loading, setValues, refetch, data } = useTestRetrieval();
const {
loading,
setValues,
refetch,
data,
onPaginationChange,
page,
pageSize,
handleFilterSubmit,
} = useTestRetrieval();
const filters: FilterCollection[] = useMemo(() => {
return [
{
field: 'doc_ids',
label: 'File',
list:
data.doc_aggs?.map((x) => ({
id: x.doc_id,
label: x.doc_name,
count: x.count,
})) ?? [],
},
];
}, [data.doc_aggs]);
return (
<section className="flex divide-x h-full">
<div className="p-4">
<TestingForm
loading={loading}
setValues={setValues}
refetch={refetch}
></TestingForm>
</div>
<div className="p-4 flex-1 ">
<h2 className="text-4xl font-bold mb-8 px-[10%]">
15 Results from 3 files
</h2>
<section className="flex flex-col gap-4 overflow-auto h-[83vh] px-[10%]">
{data.chunks.map((x) => (
<Card
key={x.chunk_id}
className="bg-colors-background-neutral-weak border-colors-outline-neutral-strong"
>
<CardHeader>
<CardTitle>
<div className="flex gap-2 flex-wrap">
<ChunkTitle item={x}></ChunkTitle>
</div>
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-colors-text-neutral-strong">
{x.content_with_weight}
</p>
</CardContent>
</Card>
))}
</section>
</div>
</section>
<div className="p-5">
<section className="flex justify-between items-center">
<TopTitle
title={'Configuration'}
description={` Update your knowledge base configuration here, particularly the chunk
method.`}
></TopTitle>
<Button>Save as Preset</Button>
</section>
<section className="flex divide-x h-full">
<div className="p-4 flex-1">
<div className="flex justify-between pb-2.5">
<span className="text-text-title font-semibold text-2xl">
Test setting
</span>
<Button variant={'outline'}>
<Plus /> Add New Test
</Button>
</div>
<TestingForm
loading={loading}
setValues={setValues}
refetch={refetch}
></TestingForm>
</div>
<div className="p-4 flex-1">
<div className="flex justify-between pb-2.5">
<span className="text-text-title font-semibold text-2xl">
Test results
</span>
<FilterPopover filters={filters} onChange={handleFilterSubmit}>
<FilterButton></FilterButton>
</FilterPopover>
</div>
<section className="flex flex-col gap-5 overflow-auto h-[76vh] mb-5">
{data.chunks?.map((x) => (
<FormContainer key={x.chunk_id} className="px-5 py-2.5">
<ChunkTitle item={x}></ChunkTitle>
<p className="!mt-2.5"> {x.content_with_weight}</p>
</FormContainer>
))}
</section>
<RAGFlowPagination
total={data.total}
onChange={onPaginationChange}
current={page}
pageSize={pageSize}
></RAGFlowPagination>
</div>
</section>
</div>
);
}

View File

@ -4,7 +4,12 @@ import { zodResolver } from '@hookform/resolvers/zod';
import { useForm, useWatch } from 'react-hook-form';
import { z } from 'zod';
import { RerankFormFields } from '@/components/rerank';
import { FormContainer } from '@/components/form-container';
import {
initialTopKValue,
RerankFormFields,
topKSchema,
} from '@/components/rerank';
import {
initialKeywordsSimilarityWeightValue,
initialSimilarityThresholdValue,
@ -12,6 +17,7 @@ import {
SimilaritySliderFormField,
similarityThresholdSchema,
} from '@/components/similarity-slider';
import { ButtonLoading } from '@/components/ui/button';
import {
Form,
FormControl,
@ -20,7 +26,6 @@ import {
FormLabel,
FormMessage,
} from '@/components/ui/form';
import { LoadingButton } from '@/components/ui/loading-button';
import { Textarea } from '@/components/ui/textarea';
import { UseKnowledgeGraphFormField } from '@/components/use-knowledge-graph-item';
import { useTestRetrieval } from '@/hooks/use-knowledge-request';
@ -46,6 +51,7 @@ export default function TestingForm({
}),
...similarityThresholdSchema,
...keywordsSimilarityWeightSchema,
...topKSchema,
});
const form = useForm<z.infer<typeof formSchema>>({
@ -53,6 +59,7 @@ export default function TestingForm({
defaultValues: {
...initialSimilarityThresholdValue,
...initialKeywordsSimilarityWeightValue,
...initialTopKValue,
},
});
@ -71,12 +78,14 @@ export default function TestingForm({
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<SimilaritySliderFormField
vectorSimilarityWeightName="keywords_similarity_weight"
isTooltipShown
></SimilaritySliderFormField>
<RerankFormFields></RerankFormFields>
<UseKnowledgeGraphFormField name="use_kg"></UseKnowledgeGraphFormField>
<FormContainer className="p-10">
<SimilaritySliderFormField
vectorSimilarityWeightName="keywords_similarity_weight"
isTooltipShown
></SimilaritySliderFormField>
<RerankFormFields></RerankFormFields>
<UseKnowledgeGraphFormField name="use_kg"></UseKnowledgeGraphFormField>
</FormContainer>
<FormField
control={form.control}
name="question"
@ -94,16 +103,13 @@ export default function TestingForm({
</FormItem>
)}
/>
<LoadingButton
variant={'tertiary'}
size={'sm'}
<ButtonLoading
type="submit"
className="w-full"
disabled={!!!trim(question)}
loading={loading}
>
{t('knowledgeDetails.testingLabel')}
</LoadingButton>
</ButtonLoading>
</form>
</Form>
);