| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 | 'use client'import type { FC } from 'react'import React, { useCallback, useMemo } from 'react'import { useTranslation } from 'react-i18next'import Image from 'next/image'import ProgressIndicator from '../../create/assets/progress-indicator.svg'import Reranking from '../../create/assets/rerank.svg'import cn from '@/utils/classnames'import TopKItem from '@/app/components/base/param-item/top-k-item'import ScoreThresholdItem from '@/app/components/base/param-item/score-threshold-item'import { RETRIEVE_METHOD } from '@/types/app'import Switch from '@/app/components/base/switch'import Tooltip from '@/app/components/base/tooltip'import type { RetrievalConfig } from '@/types/app'import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'import { useCurrentProviderAndModel, useModelListAndDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks'import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'import {  DEFAULT_WEIGHTED_SCORE,  RerankingModeEnum,  WeightedScoreEnum,} from '@/models/datasets'import WeightedScore from '@/app/components/app/configuration/dataset-config/params-config/weighted-score'import Toast from '@/app/components/base/toast'import RadioCard from '@/app/components/base/radio-card'type Props = {  type: RETRIEVE_METHOD  value: RetrievalConfig  onChange: (value: RetrievalConfig) => void}const RetrievalParamConfig: FC<Props> = ({  type,  value,  onChange,}) => {  const { t } = useTranslation()  const canToggleRerankModalEnable = type !== RETRIEVE_METHOD.hybrid  const isEconomical = type === RETRIEVE_METHOD.invertedIndex  const isHybridSearch = type === RETRIEVE_METHOD.hybrid  const {    modelList: rerankModelList,  } = useModelListAndDefaultModel(ModelTypeEnum.rerank)  const {    currentModel,  } = useCurrentProviderAndModel(    rerankModelList,    {      provider: value.reranking_model?.reranking_provider_name ?? '',      model: value.reranking_model?.reranking_model_name ?? '',    },  )  const handleDisabledSwitchClick = useCallback((enable: boolean) => {    if (enable && !currentModel)      Toast.notify({ type: 'error', message: t('workflow.errorMsg.rerankModelRequired') })    onChange({      ...value,      reranking_enable: enable,    })    // eslint-disable-next-line react-hooks/exhaustive-deps  }, [currentModel, onChange, value])  const rerankModel = useMemo(() => {    return {      provider_name: value.reranking_model.reranking_provider_name,      model_name: value.reranking_model.reranking_model_name,    }  }, [value.reranking_model])  const handleChangeRerankMode = (v: RerankingModeEnum) => {    if (v === value.reranking_mode)      return    const result = {      ...value,      reranking_mode: v,    }    if (!result.weights && v === RerankingModeEnum.WeightedScore) {      result.weights = {        weight_type: WeightedScoreEnum.Customized,        vector_setting: {          vector_weight: DEFAULT_WEIGHTED_SCORE.other.semantic,          embedding_provider_name: '',          embedding_model_name: '',        },        keyword_setting: {          keyword_weight: DEFAULT_WEIGHTED_SCORE.other.keyword,        },      }    }    if (v === RerankingModeEnum.RerankingModel && !currentModel)      Toast.notify({ type: 'error', message: t('workflow.errorMsg.rerankModelRequired') })    onChange(result)  }  const rerankingModeOptions = [    {      value: RerankingModeEnum.WeightedScore,      label: t('dataset.weightedScore.title'),      tips: t('dataset.weightedScore.description'),    },    {      value: RerankingModeEnum.RerankingModel,      label: t('common.modelProvider.rerankModel.key'),      tips: t('common.modelProvider.rerankModel.tip'),    },  ]  return (    <div>      {!isEconomical && !isHybridSearch && (        <div>          <div className='flex items-center space-x-2 mb-2'>            {canToggleRerankModalEnable && (              <Switch                size='md'                defaultValue={value.reranking_enable}                onChange={handleDisabledSwitchClick}              />            )}            <div className='flex items-center'>              <span className='mr-0.5 system-sm-semibold text-text-secondary'>{t('common.modelProvider.rerankModel.key')}</span>              <Tooltip                popupContent={                  <div className="w-[200px]">{t('common.modelProvider.rerankModel.tip')}</div>                }              />            </div>          </div>          {            value.reranking_enable && (              <ModelSelector                defaultModel={rerankModel && { provider: rerankModel.provider_name, model: rerankModel.model_name }}                modelList={rerankModelList}                onSelect={(v) => {                  onChange({                    ...value,                    reranking_model: {                      reranking_provider_name: v.provider,                      reranking_model_name: v.model,                    },                  })                }}              />            )          }        </div>      )}      {        !isHybridSearch && (          <div className={cn(!isEconomical && 'mt-4', 'flex space-between space-x-4')}>            <TopKItem              className='grow'              value={value.top_k}              onChange={(_key, v) => {                onChange({                  ...value,                  top_k: v,                })              }}              enable={true}            />            {(!isEconomical && !(value.search_method === RETRIEVE_METHOD.fullText && !value.reranking_enable)) && (              <ScoreThresholdItem                className='grow'                value={value.score_threshold}                onChange={(_key, v) => {                  onChange({                    ...value,                    score_threshold: v,                  })                }}                enable={value.score_threshold_enabled}                hasSwitch={true}                onSwitchChange={(_key, v) => {                  onChange({                    ...value,                    score_threshold_enabled: v,                  })                }}              />            )}          </div>        )      }      {        isHybridSearch && (          <>            <div className='flex gap-2 mb-4'>              {                rerankingModeOptions.map(option => (                  <RadioCard                    key={option.value}                    isChosen={value.reranking_mode === option.value}                    onChosen={() => handleChangeRerankMode(option.value)}                    icon={<Image src={                      option.value === RerankingModeEnum.WeightedScore                        ? ProgressIndicator                        : Reranking                    } alt=''/>}                    title={option.label}                    description={option.tips}                    className='flex-1'                  />                ))              }            </div>            {              value.reranking_mode === RerankingModeEnum.WeightedScore && (                <WeightedScore                  value={{                    value: [                      value.weights!.vector_setting.vector_weight,                      value.weights!.keyword_setting.keyword_weight,                    ],                  }}                  onChange={(v) => {                    onChange({                      ...value,                      weights: {                        ...value.weights!,                        vector_setting: {                          ...value.weights!.vector_setting,                          vector_weight: v.value[0],                        },                        keyword_setting: {                          ...value.weights!.keyword_setting,                          keyword_weight: v.value[1],                        },                      },                    })                  }}                />              )            }            {              value.reranking_mode !== RerankingModeEnum.WeightedScore && (                <ModelSelector                  defaultModel={rerankModel && { provider: rerankModel.provider_name, model: rerankModel.model_name }}                  modelList={rerankModelList}                  onSelect={(v) => {                    onChange({                      ...value,                      reranking_model: {                        reranking_provider_name: v.provider,                        reranking_model_name: v.model,                      },                    })                  }}                />              )            }            <div className={cn(!isEconomical && 'mt-4', 'flex space-between space-x-6')}>              <TopKItem                className='grow'                value={value.top_k}                onChange={(_key, v) => {                  onChange({                    ...value,                    top_k: v,                  })                }}                enable={true}              />              <ScoreThresholdItem                className='grow'                value={value.score_threshold}                onChange={(_key, v) => {                  onChange({                    ...value,                    score_threshold: v,                  })                }}                enable={value.score_threshold_enabled}                hasSwitch={true}                onSwitchChange={(_key, v) => {                  onChange({                    ...value,                    score_threshold_enabled: v,                  })                }}              />            </div>          </>        )      }    </div>  )}export default React.memo(RetrievalParamConfig)
 |