mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-09-08 10:14:35 +08:00
154 lines
5.3 KiB
TypeScript
154 lines
5.3 KiB
TypeScript
import { FormLayout } from '@/constants/form';
|
|
import { useTranslate } from '@/hooks/common-hooks';
|
|
import { cn } from '@/lib/utils';
|
|
import { useFormContext } from 'react-hook-form';
|
|
import { z } from 'zod';
|
|
import { SliderInputFormField } from '../slider-input-form-field';
|
|
import { SingleFormSlider } from '../ui/dual-range-slider';
|
|
import {
|
|
FormControl,
|
|
FormField,
|
|
FormItem,
|
|
FormLabel,
|
|
FormMessage,
|
|
} from '../ui/form';
|
|
import { NumberInput } from '../ui/input';
|
|
|
|
interface SimilaritySliderFormFieldProps {
|
|
similarityName?: string;
|
|
similarityWeightName?: string;
|
|
similarityWeightType?: 'vector' | 'keyword';
|
|
isTooltipShown?: boolean;
|
|
numberInputClassName?: string;
|
|
}
|
|
|
|
export const initialSimilarityThresholdValue = {
|
|
similarity_threshold: 0.2,
|
|
};
|
|
export const initialKeywordsSimilarityWeightValue = {
|
|
keywords_similarity_weight: 0.7,
|
|
};
|
|
|
|
export const similarityThresholdSchema = { similarity_threshold: z.number() };
|
|
|
|
export const keywordsSimilarityWeightSchema = {
|
|
keywords_similarity_weight: z.number().min(0).max(1),
|
|
};
|
|
|
|
export const vectorSimilarityWeightSchema = {
|
|
vector_similarity_weight: z.number(),
|
|
};
|
|
|
|
export const initialVectorSimilarityWeightValue = {
|
|
vector_similarity_weight: 0.3,
|
|
};
|
|
|
|
export function SimilaritySliderFormField({
|
|
similarityName = 'similarity_threshold',
|
|
similarityWeightName = 'vector_similarity_weight',
|
|
similarityWeightType = 'vector',
|
|
isTooltipShown,
|
|
numberInputClassName,
|
|
}: SimilaritySliderFormFieldProps) {
|
|
const { t } = useTranslate('knowledgeDetails');
|
|
const form = useFormContext();
|
|
const isVector = similarityWeightType === 'vector';
|
|
const normalizeWeight = (weight: number) =>
|
|
Number(Math.min(1, Math.max(0, weight)).toFixed(2));
|
|
const getVectorWeight = (weight: number) =>
|
|
normalizeWeight(isVector ? weight : 1 - weight);
|
|
const getFullTextWeight = (weight: number) =>
|
|
normalizeWeight(isVector ? 1 - weight : weight);
|
|
const getStoredWeight = (vectorWeight: number) =>
|
|
normalizeWeight(isVector ? vectorWeight : 1 - vectorWeight);
|
|
|
|
return (
|
|
<>
|
|
<SliderInputFormField
|
|
name={similarityName}
|
|
label={t('similarityThreshold')}
|
|
max={1}
|
|
step={0.01}
|
|
layout={FormLayout.Vertical}
|
|
tooltip={isTooltipShown && t('similarityThresholdTip')}
|
|
numberInputClassName={numberInputClassName}
|
|
></SliderInputFormField>
|
|
<FormField
|
|
control={form.control}
|
|
name={similarityWeightName}
|
|
defaultValue={0}
|
|
render={({ field }) => (
|
|
<FormItem
|
|
// className={cn({ 'flex items-center gap-1 space-y-0': isHorizontal })}
|
|
>
|
|
<FormLabel
|
|
tooltip={
|
|
isTooltipShown &&
|
|
t(
|
|
isVector
|
|
? 'vectorSimilarityWeightTip'
|
|
: 'keywordSimilarityWeightTip',
|
|
)
|
|
}
|
|
>
|
|
{t(
|
|
isVector ? 'vectorSimilarityWeight' : 'keywordSimilarityWeight',
|
|
)}
|
|
</FormLabel>
|
|
<div className={cn('flex items-end gap-4 justify-between')}>
|
|
<FormControl>
|
|
<div className="flex flex-col flex-1 gap-2">
|
|
<div className="flex justify-between items-center">
|
|
<div className="flex items-center gap-1">
|
|
<label className="italic text-xs text-text-secondary">
|
|
vector
|
|
</label>
|
|
<span className="bg-bg-card rounded-md p-1 w-10 text-center text-xs">
|
|
{getVectorWeight(field.value).toFixed(2)}
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center gap-1">
|
|
<label className="italic text-xs text-text-secondary">
|
|
full-text
|
|
</label>
|
|
<span className="bg-bg-card rounded-md p-1 w-10 text-center text-xs">
|
|
{getFullTextWeight(field.value).toFixed(2)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<SingleFormSlider
|
|
{...field}
|
|
value={getVectorWeight(field.value)}
|
|
onChange={(value) => field.onChange(getStoredWeight(value))}
|
|
max={1}
|
|
step={0.01}
|
|
min={0}
|
|
></SingleFormSlider>
|
|
</div>
|
|
</FormControl>
|
|
<FormControl>
|
|
<NumberInput
|
|
className={cn(
|
|
'h-6 w-10 p-0 text-center bg-bg-input border-border-button border text-text-secondary',
|
|
'[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',
|
|
numberInputClassName,
|
|
)}
|
|
max={1}
|
|
min={0}
|
|
step={0.01}
|
|
{...field}
|
|
value={getVectorWeight(field.value)}
|
|
onChange={(value) =>
|
|
field.onChange(getStoredWeight(Number(value)))
|
|
}
|
|
></NumberInput>
|
|
</FormControl>
|
|
</div>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
</>
|
|
);
|
|
}
|