mirror of
https://github.com/langgenius/dify.git
synced 2025-12-28 02:22:15 +00:00
i18n
This commit is contained in:
parent
7898dbd5bf
commit
7bce35913d
@ -1,3 +1,4 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
GeneralChunk,
|
||||
ParentChildChunk,
|
||||
@ -8,6 +9,7 @@ import { ChunkStructureEnum } from '../../types'
|
||||
import type { Option } from './type'
|
||||
|
||||
export const useChunkStructure = () => {
|
||||
const { t } = useTranslation()
|
||||
const GeneralOption: Option = {
|
||||
id: ChunkStructureEnum.general,
|
||||
icon: (isActive: boolean) => (
|
||||
@ -17,8 +19,8 @@ export const useChunkStructure = () => {
|
||||
isActive && 'text-util-colors-indigo-indigo-600',
|
||||
)} />
|
||||
),
|
||||
title: 'General',
|
||||
description: 'General text chunking mode, the chunks retrieved and recalled are the same.',
|
||||
title: t('datasetCreation.stepTwo.general'),
|
||||
description: t('datasetCreation.stepTwo.generalTip'),
|
||||
effectColor: 'blue',
|
||||
}
|
||||
const ParentChildOption: Option = {
|
||||
@ -31,8 +33,8 @@ export const useChunkStructure = () => {
|
||||
)}
|
||||
/>
|
||||
),
|
||||
title: 'Parent-Child',
|
||||
description: 'Parent-child text chunking mode, the chunks retrieved and recalled are different.',
|
||||
title: t('datasetCreation.stepTwo.parentChild'),
|
||||
description: t('datasetCreation.stepTwo.parentChildTip'),
|
||||
effectColor: 'blue-light',
|
||||
}
|
||||
const QuestionAnswerOption: Option = {
|
||||
|
||||
@ -2,6 +2,7 @@ import {
|
||||
memo,
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Field } from '@/app/components/workflow/nodes/_base/components/layout'
|
||||
import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
|
||||
import { useModelListAndDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
@ -23,30 +24,31 @@ const EmbeddingModel = ({
|
||||
onEmbeddingModelChange,
|
||||
readonly = false,
|
||||
}: EmbeddingModelProps) => {
|
||||
const { t } = useTranslation()
|
||||
const {
|
||||
modelList: embeddingModelList,
|
||||
} = useModelListAndDefaultModel(ModelTypeEnum.textEmbedding)
|
||||
const embeddingModelConfig = useMemo(() => {
|
||||
if (!embeddingModel || !embeddingModelProvider)
|
||||
return undefined
|
||||
const embeddingModelConfig = useMemo(() => {
|
||||
if (!embeddingModel || !embeddingModelProvider)
|
||||
return undefined
|
||||
|
||||
return {
|
||||
providerName: embeddingModelProvider,
|
||||
modelName: embeddingModel,
|
||||
return {
|
||||
providerName: embeddingModelProvider,
|
||||
modelName: embeddingModel,
|
||||
}
|
||||
}, [embeddingModel, embeddingModelProvider])
|
||||
|
||||
const handleRerankingModelChange = (model: DefaultModel) => {
|
||||
onEmbeddingModelChange?.({
|
||||
embeddingModelProvider: model.provider,
|
||||
embeddingModel: model.model,
|
||||
})
|
||||
}
|
||||
}, [embeddingModel, embeddingModelProvider])
|
||||
|
||||
const handleRerankingModelChange = (model: DefaultModel) => {
|
||||
onEmbeddingModelChange?.({
|
||||
embeddingModelProvider: model.provider,
|
||||
embeddingModel: model.model,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Field
|
||||
fieldTitleProps={{
|
||||
title: 'Embedding Model',
|
||||
title: t('datasetSettings.form.embeddingModel'),
|
||||
}}
|
||||
>
|
||||
<ModelSelector
|
||||
|
||||
@ -52,7 +52,7 @@ const IndexMethod = ({
|
||||
return (
|
||||
<Field
|
||||
fieldTitleProps={{
|
||||
title: 'Index method',
|
||||
title: t('datasetCreation.stepTwo.indexMode'),
|
||||
}}
|
||||
>
|
||||
<div className='space-y-1'>
|
||||
|
||||
@ -3,6 +3,7 @@ import {
|
||||
memo,
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import cn from '@/utils/classnames'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import {
|
||||
@ -53,6 +54,7 @@ const OptionCard = memo(({
|
||||
onClick,
|
||||
readonly,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const isActive = useMemo(() => {
|
||||
return id === selectedId
|
||||
}, [id, selectedId])
|
||||
@ -103,7 +105,7 @@ const OptionCard = memo(({
|
||||
{
|
||||
isRecommended && (
|
||||
<Badge className='ml-1 h-4 border-text-accent-secondary text-text-accent-secondary'>
|
||||
Recommend
|
||||
{t('datasetCreation.stepTwo.recommend')}
|
||||
</Badge>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
FullTextSearch,
|
||||
HybridSearch,
|
||||
@ -15,57 +16,58 @@ import type {
|
||||
} from './type'
|
||||
|
||||
export const useRetrievalSetting = (indexMethod: IndexMethodEnum) => {
|
||||
const { t } = useTranslation()
|
||||
const VectorSearchOption: Option = useMemo(() => {
|
||||
return {
|
||||
id: RetrievalSearchMethodEnum.semantic,
|
||||
icon: VectorSearch as any,
|
||||
title: 'Vector Search',
|
||||
description: 'Generate query embeddings and search for the text chunk most similar to its vector representation.',
|
||||
title: t('dataset.retrieval.semantic_search.title'),
|
||||
description: t('dataset.retrieval.semantic_search.description'),
|
||||
effectColor: 'purple',
|
||||
}
|
||||
}, [])
|
||||
}, [t])
|
||||
const FullTextSearchOption: Option = useMemo(() => {
|
||||
return {
|
||||
id: RetrievalSearchMethodEnum.fullText,
|
||||
icon: FullTextSearch as any,
|
||||
title: 'Full-Text Search',
|
||||
description: 'Execute full-text search and vector searches simultaneously, re-rank to select the best match for the user\'s query. Users can choose to set weights or configure to a Rerank model.',
|
||||
title: t('dataset.retrieval.full_text_search.title'),
|
||||
description: t('dataset.retrieval.full_text_search.description'),
|
||||
effectColor: 'purple',
|
||||
}
|
||||
}, [])
|
||||
}, [t])
|
||||
const HybridSearchOption: Option = useMemo(() => {
|
||||
return {
|
||||
id: RetrievalSearchMethodEnum.hybrid,
|
||||
icon: HybridSearch as any,
|
||||
title: 'Hybrid Search',
|
||||
description: 'Execute full-text search and vector searches simultaneously, re-rank to select the best match for the user\'s query. Users can choose to set weights or configure to a Rerank model.',
|
||||
title: t('dataset.retrieval.hybrid_search.title'),
|
||||
description: t('dataset.retrieval.hybrid_search.description'),
|
||||
effectColor: 'purple',
|
||||
}
|
||||
}, [])
|
||||
}, [t])
|
||||
const InvertedIndexOption: Option = useMemo(() => {
|
||||
return {
|
||||
id: RetrievalSearchMethodEnum.invertedIndex,
|
||||
icon: HybridSearch as any,
|
||||
title: 'Inverted Index',
|
||||
description: 'Use inverted index to search for the most relevant text chunks.',
|
||||
title: t('dataset.retrieval.invertedIndex.title'),
|
||||
description: t('dataset.retrieval.invertedIndex.description'),
|
||||
effectColor: 'purple',
|
||||
}
|
||||
}, [])
|
||||
}, [t])
|
||||
|
||||
const WeightedScoreModeOption: HybridSearchModeOption = useMemo(() => {
|
||||
return {
|
||||
id: HybridSearchModeEnum.WeightedScore,
|
||||
title: 'Weighted Score',
|
||||
description: 'By adjusting the weights assigned, this rerank strategy determines whether to prioritize semantic or keyword matching.',
|
||||
title: t('dataset.weightedScore.title'),
|
||||
description: t('dataset.weightedScore.description'),
|
||||
}
|
||||
}, [])
|
||||
}, [t])
|
||||
const RerankModelModeOption: HybridSearchModeOption = useMemo(() => {
|
||||
return {
|
||||
id: HybridSearchModeEnum.RerankingModel,
|
||||
title: 'Rerank Model',
|
||||
description: 'Rerank model will reorder the candidate document list based on the semantic match with user query, improving the results of semantic ranking.',
|
||||
title: t('common.modelProvider.rerankModel.key'),
|
||||
description: t('common.modelProvider.rerankModel.tip'),
|
||||
}
|
||||
}, [])
|
||||
}, [t])
|
||||
|
||||
return useMemo(() => ({
|
||||
options: indexMethod === IndexMethodEnum.ECONOMICAL ? [
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import {
|
||||
memo,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Field } from '@/app/components/workflow/nodes/_base/components/layout'
|
||||
import type {
|
||||
HybridSearchModeEnum,
|
||||
@ -22,6 +23,8 @@ type RetrievalSettingProps = {
|
||||
onRetrievalSearchMethodChange: (value: RetrievalSearchMethodEnum) => void
|
||||
hybridSearchMode: HybridSearchModeEnum
|
||||
onHybridSearchModeChange: (value: HybridSearchModeEnum) => void
|
||||
rerankingModelEnabled?: boolean
|
||||
onRerankingModelEnabledChange?: (value: boolean) => void
|
||||
weightedScore?: WeightedScore
|
||||
onWeightedScoreChange: (value: { value: number[] }) => void
|
||||
} & RerankingModelSelectorProps & TopKAndScoreThresholdProps
|
||||
@ -35,6 +38,8 @@ const RetrievalSetting = ({
|
||||
onHybridSearchModeChange,
|
||||
weightedScore,
|
||||
onWeightedScoreChange,
|
||||
rerankingModelEnabled,
|
||||
onRerankingModelEnabledChange,
|
||||
rerankingModel,
|
||||
onRerankingModelChange,
|
||||
topK,
|
||||
@ -44,6 +49,7 @@ const RetrievalSetting = ({
|
||||
isScoreThresholdEnabled,
|
||||
onScoreThresholdEnabledChange,
|
||||
}: RetrievalSettingProps) => {
|
||||
const { t } = useTranslation()
|
||||
const {
|
||||
options,
|
||||
hybridSearchModeOptions,
|
||||
@ -52,16 +58,10 @@ const RetrievalSetting = ({
|
||||
return (
|
||||
<Field
|
||||
fieldTitleProps={{
|
||||
title: 'Retrieval Setting',
|
||||
title: t('datasetSettings.form.retrievalSetting.title'),
|
||||
subTitle: (
|
||||
<div className='body-xs-regular flex items-center text-text-tertiary'>
|
||||
<a
|
||||
href=''
|
||||
className='text-text-accent'
|
||||
target='_blank'
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
<a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings' className='text-text-accent'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
|
||||
|
||||
about retrieval method.
|
||||
</div>
|
||||
@ -87,6 +87,8 @@ const RetrievalSetting = ({
|
||||
onScoreThresholdChange={onScoreThresholdChange}
|
||||
isScoreThresholdEnabled={isScoreThresholdEnabled}
|
||||
onScoreThresholdEnabledChange={onScoreThresholdEnabledChange}
|
||||
rerankingModelEnabled={rerankingModelEnabled}
|
||||
onRerankingModelEnabledChange={onRerankingModelEnabledChange}
|
||||
rerankingModel={rerankingModel}
|
||||
onRerankingModelChange={onRerankingModelChange}
|
||||
readonly={readonly}
|
||||
|
||||
@ -3,9 +3,12 @@ import {
|
||||
useCallback,
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import cn from '@/utils/classnames'
|
||||
import WeightedScoreComponent from '@/app/components/app/configuration/dataset-config/params-config/weighted-score'
|
||||
import { DEFAULT_WEIGHTED_SCORE } from '@/models/datasets'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import {
|
||||
HybridSearchModeEnum,
|
||||
RetrievalSearchMethodEnum,
|
||||
@ -33,6 +36,8 @@ type SearchMethodOptionProps = {
|
||||
onHybridSearchModeChange: (value: HybridSearchModeEnum) => void
|
||||
weightedScore?: WeightedScore
|
||||
onWeightedScoreChange: (value: { value: number[] }) => void
|
||||
rerankingModelEnabled?: boolean
|
||||
onRerankingModelEnabledChange?: (value: boolean) => void
|
||||
} & RerankingModelSelectorProps & TopKAndScoreThresholdProps
|
||||
const SearchMethodOption = ({
|
||||
readonly,
|
||||
@ -44,6 +49,8 @@ const SearchMethodOption = ({
|
||||
onHybridSearchModeChange,
|
||||
weightedScore,
|
||||
onWeightedScoreChange,
|
||||
rerankingModelEnabled,
|
||||
onRerankingModelEnabledChange,
|
||||
rerankingModel,
|
||||
onRerankingModelChange,
|
||||
topK,
|
||||
@ -53,6 +60,7 @@ const SearchMethodOption = ({
|
||||
isScoreThresholdEnabled,
|
||||
onScoreThresholdEnabledChange,
|
||||
}: SearchMethodOptionProps) => {
|
||||
const { t } = useTranslation()
|
||||
const Icon = option.icon
|
||||
const isHybridSearch = option.id === RetrievalSearchMethodEnum.hybrid
|
||||
const isHybridSearchWeightedScoreMode = hybridSearchMode === HybridSearchModeEnum.WeightedScore
|
||||
@ -82,6 +90,28 @@ const SearchMethodOption = ({
|
||||
return isActive ? 'border-[1.5px] bg-components-option-card-option-selected-bg' : ''
|
||||
}, [])
|
||||
|
||||
const showRerankModelSelectorSwitch = useMemo(() => {
|
||||
if (searchMethod === RetrievalSearchMethodEnum.semantic)
|
||||
return true
|
||||
|
||||
if (searchMethod === RetrievalSearchMethodEnum.fullText)
|
||||
return true
|
||||
|
||||
return false
|
||||
}, [searchMethod])
|
||||
const showRerankModelSelector = useMemo(() => {
|
||||
if (searchMethod === RetrievalSearchMethodEnum.semantic)
|
||||
return true
|
||||
|
||||
if (searchMethod === RetrievalSearchMethodEnum.fullText)
|
||||
return true
|
||||
|
||||
if (searchMethod === RetrievalSearchMethodEnum.hybrid && hybridSearchMode !== HybridSearchModeEnum.WeightedScore)
|
||||
return true
|
||||
|
||||
return false
|
||||
}, [hybridSearchMode, searchMethod])
|
||||
|
||||
return (
|
||||
<OptionCard
|
||||
key={option.id}
|
||||
@ -129,12 +159,31 @@ const SearchMethodOption = ({
|
||||
)
|
||||
}
|
||||
{
|
||||
!(isHybridSearch && hybridSearchMode === HybridSearchModeEnum.WeightedScore) && (
|
||||
<RerankingModelSelector
|
||||
rerankingModel={rerankingModel}
|
||||
onRerankingModelChange={onRerankingModelChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
showRerankModelSelector && (
|
||||
<div>
|
||||
{
|
||||
showRerankModelSelectorSwitch && (
|
||||
<div className='system-sm-semibold mb-1 flex items-center text-text-secondary'>
|
||||
<Switch
|
||||
className='mr-1'
|
||||
defaultValue={rerankingModelEnabled}
|
||||
onChange={onRerankingModelEnabledChange}
|
||||
disabled={readonly}
|
||||
/>
|
||||
{t('common.modelProvider.rerankModel.key')}
|
||||
<Tooltip
|
||||
triggerClassName='ml-0.5 shrink-0 w-3.5 h-3.5'
|
||||
popupContent={t('common.modelProvider.rerankModel.tip')}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<RerankingModelSelector
|
||||
rerankingModel={rerankingModel}
|
||||
onRerankingModelChange={onRerankingModelChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<TopKAndScoreThreshold
|
||||
@ -145,6 +194,7 @@ const SearchMethodOption = ({
|
||||
isScoreThresholdEnabled={isScoreThresholdEnabled}
|
||||
onScoreThresholdEnabledChange={onScoreThresholdEnabledChange}
|
||||
readonly={readonly}
|
||||
hiddenScoreThreshold={searchMethod === RetrievalSearchMethodEnum.invertedIndex}
|
||||
/>
|
||||
</div>
|
||||
</OptionCard>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
@ -11,6 +12,7 @@ export type TopKAndScoreThresholdProps = {
|
||||
isScoreThresholdEnabled?: boolean
|
||||
onScoreThresholdEnabledChange?: (value: boolean) => void
|
||||
readonly?: boolean
|
||||
hiddenScoreThreshold?: boolean
|
||||
}
|
||||
const TopKAndScoreThreshold = ({
|
||||
topK,
|
||||
@ -20,7 +22,9 @@ const TopKAndScoreThreshold = ({
|
||||
isScoreThresholdEnabled,
|
||||
onScoreThresholdEnabledChange,
|
||||
readonly,
|
||||
hiddenScoreThreshold,
|
||||
}: TopKAndScoreThresholdProps) => {
|
||||
const { t } = useTranslation()
|
||||
const handleTopKChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = Number(e.target.value)
|
||||
if (Number.isNaN(value))
|
||||
@ -39,10 +43,10 @@ const TopKAndScoreThreshold = ({
|
||||
<div className='grid grid-cols-2 gap-4'>
|
||||
<div>
|
||||
<div className='system-xs-medium mb-0.5 flex h-6 items-center text-text-secondary'>
|
||||
Top k
|
||||
{t('appDebug.datasetConfig.top_k')}
|
||||
<Tooltip
|
||||
triggerClassName='ml-0.5 shrink-0 w-3.5 h-3.5'
|
||||
popupContent='top k'
|
||||
popupContent={t('appDebug.datasetConfig.top_kTip')}
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
@ -52,29 +56,33 @@ const TopKAndScoreThreshold = ({
|
||||
disabled={readonly}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className='mb-0.5 flex h-6 items-center'>
|
||||
<Switch
|
||||
className='mr-2'
|
||||
defaultValue={isScoreThresholdEnabled}
|
||||
onChange={onScoreThresholdEnabledChange}
|
||||
disabled={readonly}
|
||||
/>
|
||||
<div className='system-sm-medium grow truncate text-text-secondary'>
|
||||
Score Threshold
|
||||
{
|
||||
!hiddenScoreThreshold && (
|
||||
<div>
|
||||
<div className='mb-0.5 flex h-6 items-center'>
|
||||
<Switch
|
||||
className='mr-2'
|
||||
defaultValue={isScoreThresholdEnabled}
|
||||
onChange={onScoreThresholdEnabledChange}
|
||||
disabled={readonly}
|
||||
/>
|
||||
<div className='system-sm-medium grow truncate text-text-secondary'>
|
||||
{t('appDebug.datasetConfig.score_threshold')}
|
||||
</div>
|
||||
<Tooltip
|
||||
triggerClassName='shrink-0 ml-0.5 w-3.5 h-3.5'
|
||||
popupContent={t('appDebug.datasetConfig.score_thresholdTip')}
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
type='number'
|
||||
value={scoreThreshold}
|
||||
onChange={handleScoreThresholdChange}
|
||||
disabled={readonly || !isScoreThresholdEnabled}
|
||||
/>
|
||||
</div>
|
||||
<Tooltip
|
||||
triggerClassName='shrink-0 ml-0.5 w-3.5 h-3.5'
|
||||
popupContent='Score Threshold'
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
type='number'
|
||||
value={scoreThreshold}
|
||||
onChange={handleScoreThresholdChange}
|
||||
disabled={readonly}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,17 +1,19 @@
|
||||
import type { FC } from 'react'
|
||||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { KnowledgeBaseNodeType } from './types'
|
||||
import type { NodeProps } from '@/app/components/workflow/types'
|
||||
|
||||
const Node: FC<NodeProps<KnowledgeBaseNodeType>> = ({ data }) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div className='mb-1 space-y-0.5 px-3 py-1'>
|
||||
<div className='flex h-6 items-center rounded-md bg-workflow-block-parma-bg px-1.5'>
|
||||
<div className='system-xs-medium-uppercase mr-2 shrink-0 text-text-tertiary'>Index method</div>
|
||||
<div className='system-xs-medium-uppercase mr-2 shrink-0 text-text-tertiary'>{t('datasetCreation.stepTwo.indexMode')}</div>
|
||||
<div className='system-xs-medium grow truncate text-right text-text-secondary' title={data.indexing_technique}>{data.indexing_technique}</div>
|
||||
</div>
|
||||
<div className='flex h-6 items-center rounded-md bg-workflow-block-parma-bg px-1.5'>
|
||||
<div className='system-xs-medium-uppercase mr-2 shrink-0 text-text-tertiary'>Retrieval Method</div>
|
||||
<div className='system-xs-medium-uppercase mr-2 shrink-0 text-text-tertiary'>{t('datasetSettings.form.retrievalSetting.title')}</div>
|
||||
<div className='system-xs-medium grow truncate text-right text-text-secondary' title={data.retrieval_model.search_method}>{data.retrieval_model.search_method}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user