| @@ -4,6 +4,7 @@ import { memo, useMemo } from 'react' | |||
| import type { FC } from 'react' | |||
| import { useTranslation } from 'react-i18next' | |||
| import { | |||
| RiAlertFill, | |||
| RiQuestionLine, | |||
| } from '@remixicon/react' | |||
| import WeightedScore from './weighted-score' | |||
| @@ -26,7 +27,6 @@ import TooltipPlus from '@/app/components/base/tooltip-plus' | |||
| import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' | |||
| import type { | |||
| DataSet, | |||
| WeightedScoreEnum, | |||
| } from '@/models/datasets' | |||
| import { RerankingModeEnum } from '@/models/datasets' | |||
| import cn from '@/utils/classnames' | |||
| @@ -112,12 +112,11 @@ const ConfigContent: FC<Props> = ({ | |||
| }) | |||
| } | |||
| const handleWeightedScoreChange = (value: { type: WeightedScoreEnum; value: number[] }) => { | |||
| const handleWeightedScoreChange = (value: { value: number[] }) => { | |||
| const configs = { | |||
| ...datasetConfigs, | |||
| weights: { | |||
| ...datasetConfigs.weights!, | |||
| weight_type: value.type, | |||
| vector_setting: { | |||
| ...datasetConfigs.weights!.vector_setting!, | |||
| vector_weight: value.value[0], | |||
| @@ -178,14 +177,6 @@ const ConfigContent: FC<Props> = ({ | |||
| popupContent={( | |||
| <div className='w-[320px]'> | |||
| {t('dataset.nTo1RetrievalLegacy')} | |||
| <a | |||
| className='underline' | |||
| href={LEGACY_LINK_MAP[language]} | |||
| target='_blank' | |||
| rel='noopener noreferrer' | |||
| > | |||
| ({t('dataset.nTo1RetrievalLegacyLink')}) | |||
| </a> | |||
| </div> | |||
| )} | |||
| > | |||
| @@ -196,6 +187,22 @@ const ConfigContent: FC<Props> = ({ | |||
| description={t('appDebug.datasetConfig.retrieveOneWay.description')} | |||
| isChosen={type === RETRIEVE_TYPE.oneWay} | |||
| onChosen={() => { setType(RETRIEVE_TYPE.oneWay) }} | |||
| extra={( | |||
| <div className='flex pl-3 pr-1 py-3 border-t border-divider-subtle bg-state-warning-hover rounded-b-xl'> | |||
| <RiAlertFill className='shrink-0 mr-1.5 w-4 h-4 text-text-warning-secondary' /> | |||
| <div className='system-xs-medium text-text-primary'> | |||
| {t('dataset.nTo1RetrievalLegacyLinkText')} | |||
| <a | |||
| className='text-text-accent' | |||
| href={LEGACY_LINK_MAP[language]} | |||
| target='_blank' | |||
| rel='noopener noreferrer' | |||
| > | |||
| {t('dataset.nTo1RetrievalLegacyLink')} | |||
| </a> | |||
| </div> | |||
| </div> | |||
| )} | |||
| /> | |||
| <RadioCard | |||
| icon={<MultiPathRetrieval className='shrink-0 mr-3 w-9 h-9 rounded-lg' />} | |||
| @@ -302,7 +309,6 @@ const ConfigContent: FC<Props> = ({ | |||
| <div className='mt-2 space-y-4'> | |||
| <WeightedScore | |||
| value={{ | |||
| type: datasetConfigs.weights!.weight_type, | |||
| value: [ | |||
| datasetConfigs.weights!.vector_setting.vector_weight, | |||
| datasetConfigs.weights!.keyword_setting.keyword_weight, | |||
| @@ -0,0 +1,7 @@ | |||
| .weightedScoreSliderTrack { | |||
| background: var(--color-util-colors-blue-light-blue-light-500) !important; | |||
| } | |||
| .weightedScoreSliderTrack-1 { | |||
| background: transparent !important; | |||
| } | |||
| @@ -1,9 +1,6 @@ | |||
| import { memo, useCallback } from 'react' | |||
| import { memo } from 'react' | |||
| import { useTranslation } from 'react-i18next' | |||
| import { | |||
| DEFAULT_WEIGHTED_SCORE, | |||
| WeightedScoreEnum, | |||
| } from '@/models/datasets' | |||
| import './weighted-score.css' | |||
| import Slider from '@/app/components/base/slider' | |||
| import cn from '@/utils/classnames' | |||
| @@ -17,7 +14,6 @@ const formatNumber = (value: number) => { | |||
| } | |||
| type Value = { | |||
| type: WeightedScoreEnum | |||
| value: number[] | |||
| } | |||
| @@ -30,78 +26,31 @@ const WeightedScore = ({ | |||
| onChange = () => {}, | |||
| }: WeightedScoreProps) => { | |||
| const { t } = useTranslation() | |||
| const options = [ | |||
| { | |||
| value: WeightedScoreEnum.SemanticFirst, | |||
| label: t('dataset.weightedScore.semanticFirst'), | |||
| }, | |||
| { | |||
| value: WeightedScoreEnum.KeywordFirst, | |||
| label: t('dataset.weightedScore.keywordFirst'), | |||
| }, | |||
| { | |||
| value: WeightedScoreEnum.Customized, | |||
| label: t('dataset.weightedScore.customized'), | |||
| }, | |||
| ] | |||
| const disabled = value.type !== WeightedScoreEnum.Customized | |||
| const handleTypeChange = useCallback((type: WeightedScoreEnum) => { | |||
| const result = { ...value, type } | |||
| if (type === WeightedScoreEnum.SemanticFirst) | |||
| result.value = [DEFAULT_WEIGHTED_SCORE.semanticFirst.semantic, DEFAULT_WEIGHTED_SCORE.semanticFirst.keyword] | |||
| if (type === WeightedScoreEnum.KeywordFirst) | |||
| result.value = [DEFAULT_WEIGHTED_SCORE.keywordFirst.semantic, DEFAULT_WEIGHTED_SCORE.keywordFirst.keyword] | |||
| onChange(result) | |||
| }, [value, onChange]) | |||
| return ( | |||
| <div> | |||
| <div className='flex items-center mb-1 space-x-4'> | |||
| { | |||
| options.map(option => ( | |||
| <div | |||
| key={option.value} | |||
| className='flex py-1.5 max-w-[calc((100%-32px)/3)] system-sm-regular text-text-secondary cursor-pointer' | |||
| onClick={() => handleTypeChange(option.value)} | |||
| > | |||
| <div | |||
| className={cn( | |||
| 'shrink-0 mr-2 w-4 h-4 bg-components-radio-bg border border-components-radio-border rounded-full shadow-xs', | |||
| value.type === option.value && 'border-[5px] border-components-radio-border-checked', | |||
| )} | |||
| ></div> | |||
| <div className='truncate' title={option.label}>{option.label}</div> | |||
| </div> | |||
| )) | |||
| } | |||
| </div> | |||
| <div className='flex items-center px-3 h-9 space-x-3 rounded-lg border border-components-panel-border'> | |||
| <div className='shrink-0 flex items-center w-[90px] system-xs-semibold-uppercase text-util-colors-blue-blue-500'> | |||
| <div className='mr-1 truncate uppercase' title={t('dataset.weightedScore.semantic') || ''}> | |||
| {t('dataset.weightedScore.semantic')} | |||
| </div> | |||
| {formatNumber(value.value[0])} | |||
| </div> | |||
| <div className='px-3 pt-5 h-[52px] space-x-3 rounded-lg border border-components-panel-border'> | |||
| <Slider | |||
| className={cn('grow h-0.5 bg-gradient-to-r from-[#53B1FD] to-[#2ED3B7]', disabled && 'cursor-not-allowed')} | |||
| className={cn('grow h-0.5 !bg-util-colors-teal-teal-500 rounded-full')} | |||
| max={1.0} | |||
| min={0} | |||
| step={0.1} | |||
| value={value.value[0]} | |||
| onChange={v => onChange({ type: value.type, value: [v, (10 - v * 10) / 10] })} | |||
| disabled={disabled} | |||
| thumbClassName={cn(disabled && '!cursor-not-allowed')} | |||
| trackClassName='!bg-transparent' | |||
| onChange={v => onChange({ value: [v, (10 - v * 10) / 10] })} | |||
| trackClassName='weightedScoreSliderTrack' | |||
| /> | |||
| <div className='shrink-0 flex items-center justify-end w-[90px] system-xs-semibold-uppercase text-util-colors-cyan-cyan-500'> | |||
| {formatNumber(value.value[1])} | |||
| <div className='ml-1 truncate uppercase' title={t('dataset.weightedScore.keyword') || ''}> | |||
| {t('dataset.weightedScore.keyword')} | |||
| <div className='flex justify-between mt-1'> | |||
| <div className='shrink-0 flex items-center w-[90px] system-xs-semibold-uppercase text-util-colors-blue-light-blue-light-500'> | |||
| <div className='mr-1 truncate uppercase' title={t('dataset.weightedScore.semantic') || ''}> | |||
| {t('dataset.weightedScore.semantic')} | |||
| </div> | |||
| {formatNumber(value.value[0])} | |||
| </div> | |||
| <div className='shrink-0 flex items-center justify-end w-[90px] system-xs-semibold-uppercase text-util-colors-teal-teal-500'> | |||
| {formatNumber(value.value[1])} | |||
| <div className='ml-1 truncate uppercase' title={t('dataset.weightedScore.keyword') || ''}> | |||
| {t('dataset.weightedScore.keyword')} | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -12,6 +12,7 @@ type Props = { | |||
| onChosen: () => void | |||
| chosenConfig?: React.ReactNode | |||
| icon?: JSX.Element | |||
| extra?: React.ReactNode | |||
| } | |||
| const RadioCard: FC<Props> = ({ | |||
| @@ -20,20 +21,24 @@ const RadioCard: FC<Props> = ({ | |||
| isChosen, | |||
| onChosen, | |||
| icon, | |||
| extra, | |||
| }) => { | |||
| return ( | |||
| <div | |||
| className={cn(s.item, isChosen && s.active, 'flex')} | |||
| className={cn(s.item, isChosen && s.active)} | |||
| onClick={onChosen} | |||
| > | |||
| {icon} | |||
| <div> | |||
| <div className='flex justify-between items-center'> | |||
| <div className='leading-5 text-sm font-medium text-gray-900'>{title}</div> | |||
| <div className={s.radio}></div> | |||
| <div className='flex px-3 py-2'> | |||
| {icon} | |||
| <div> | |||
| <div className='flex justify-between items-center'> | |||
| <div className='leading-5 text-sm font-medium text-gray-900'>{title}</div> | |||
| <div className={s.radio}></div> | |||
| </div> | |||
| <div className='leading-[18px] text-xs font-normal text-gray-500'>{description}</div> | |||
| </div> | |||
| <div className='leading-[18px] text-xs font-normal text-gray-500'>{description}</div> | |||
| </div> | |||
| {extra} | |||
| </div> | |||
| ) | |||
| } | |||
| @@ -1,5 +1,5 @@ | |||
| .item { | |||
| @apply relative p-4 rounded-xl border border-gray-100 cursor-pointer; | |||
| @apply relative rounded-xl border border-gray-100 cursor-pointer; | |||
| background-color: #fcfcfd; | |||
| } | |||
| @@ -2,7 +2,6 @@ import type { CommonNodeType, ModelConfig, ValueSelector } from '@/app/component | |||
| import type { RETRIEVE_TYPE } from '@/types/app' | |||
| import type { | |||
| RerankingModeEnum, | |||
| WeightedScoreEnum, | |||
| } from '@/models/datasets' | |||
| export type MultipleRetrievalConfig = { | |||
| @@ -14,7 +13,6 @@ export type MultipleRetrievalConfig = { | |||
| } | |||
| reranking_mode?: RerankingModeEnum | |||
| weights?: { | |||
| weight_type: WeightedScoreEnum | |||
| vector_setting: { | |||
| vector_weight: number | |||
| embedding_provider_name: string | |||
| @@ -263,7 +263,7 @@ const useConfig = (id: string, payload: KnowledgeRetrievalNodeType) => { | |||
| handleMultipleRetrievalConfigChange, | |||
| handleModelChanged, | |||
| handleCompletionParamsChange, | |||
| selectedDatasets, | |||
| selectedDatasets: selectedDatasets.filter(d => d.name), | |||
| handleOnDatasetsChange, | |||
| isShowSingleRun, | |||
| hideSingleRun, | |||
| @@ -7,7 +7,6 @@ import type { | |||
| import { | |||
| DEFAULT_WEIGHTED_SCORE, | |||
| RerankingModeEnum, | |||
| WeightedScoreEnum, | |||
| } from '@/models/datasets' | |||
| import { RETRIEVE_METHOD } from '@/types/app' | |||
| import { DATASET_DEFAULT } from '@/config' | |||
| @@ -100,7 +99,6 @@ export const getMultipleRetrievalConfig = (multipleRetrievalConfig: MultipleRetr | |||
| if (allHighQuality && !inconsistentEmbeddingModel && (reranking_mode === RerankingModeEnum.WeightedScore || reranking_mode === undefined) && !weights) { | |||
| result.weights = { | |||
| weight_type: WeightedScoreEnum.Customized, | |||
| vector_setting: { | |||
| vector_weight: allHighQualityVectorSearch | |||
| ? DEFAULT_WEIGHTED_SCORE.allHighQualityVectorSearch.semantic | |||
| @@ -70,6 +70,7 @@ const translation = { | |||
| }, | |||
| nTo1RetrievalLegacy: 'N-to-1 retrieval will be officially deprecated from September. It is recommended to use the latest Multi-path retrieval to obtain better results. ', | |||
| nTo1RetrievalLegacyLink: 'Learn more', | |||
| nTo1RetrievalLegacyLinkText: ' N-to-1 retrieval will be officially deprecated in September.', | |||
| } | |||
| export default translation | |||
| @@ -70,6 +70,7 @@ const translation = { | |||
| }, | |||
| nTo1RetrievalLegacy: '9 月 1 日起我们将不再提供此能力,推荐使用最新的多路召回获得更好的检索效果。', | |||
| nTo1RetrievalLegacyLink: '了解更多', | |||
| nTo1RetrievalLegacyLinkText: '9 月 1 日起我们将不再提供此能力。', | |||
| } | |||
| export default translation | |||
| @@ -1,7 +1,6 @@ | |||
| import type { AgentStrategy, ModelModeType, RETRIEVE_TYPE, ToolItem, TtsAutoPlay } from '@/types/app' | |||
| import type { | |||
| RerankingModeEnum, | |||
| WeightedScoreEnum, | |||
| } from '@/models/datasets' | |||
| export type Inputs = Record<string, string | number | object> | |||
| @@ -157,7 +156,6 @@ export type DatasetConfigs = { | |||
| } | |||
| reranking_mode?: RerankingModeEnum | |||
| weights?: { | |||
| weight_type: WeightedScoreEnum | |||
| vector_setting: { | |||
| vector_weight: number | |||
| embedding_provider_name: string | |||