| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 | 'use client'import type { FC } from 'react'import React, { useCallback } from 'react'import { useTranslation } from 'react-i18next'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'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 {    defaultModel: rerankDefaultModel,    modelList: rerankModelList,  } = useModelListAndDefaultModel(ModelTypeEnum.rerank)  const {    currentModel,  } = useCurrentProviderAndModel(    rerankModelList,    rerankDefaultModel      ? {        ...rerankDefaultModel,        provider: rerankDefaultModel.provider.provider,      }      : undefined,  )  const handleDisabledSwitchClick = useCallback(() => {    if (!currentModel)      Toast.notify({ type: 'error', message: t('workflow.errorMsg.rerankModelRequired') })  }, [currentModel, rerankDefaultModel, t])  const isHybridSearch = type === RETRIEVE_METHOD.hybrid  const rerankModel = (() => {    if (value.reranking_model) {      return {        provider_name: value.reranking_model.reranking_provider_name,        model_name: value.reranking_model.reranking_model_name,      }    }    else if (rerankDefaultModel) {      return {        provider_name: rerankDefaultModel.provider.provider,        model_name: rerankDefaultModel.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,        },      }    }    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 h-8 items-center text-[13px] font-medium text-gray-900 space-x-2'>            {canToggleRerankModalEnable && (              <div                className='flex items-center'                onClick={handleDisabledSwitchClick}              >                <Switch                  size='md'                  defaultValue={currentModel ? value.reranking_enable : false}                  onChange={(v) => {                    onChange({                      ...value,                      reranking_enable: v,                    })                  }}                  disabled={!currentModel}                />              </div>            )}            <div className='flex items-center'>              <span className='mr-0.5'>{t('common.modelProvider.rerankModel.key')}</span>              <Tooltip                popupContent={                  <div className="w-[200px]">{t('common.modelProvider.rerankModel.tip')}</div>                }              />            </div>          </div>          <ModelSelector            triggerClassName={`${!value.reranking_enable && '!opacity-60 !cursor-not-allowed'}`}            defaultModel={rerankModel && { provider: rerankModel.provider_name, model: rerankModel.model_name }}            modelList={rerankModelList}            readonly={!value.reranking_enable}            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-6')}>            <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 items-center justify-between'>              {                rerankingModeOptions.map(option => (                  <div                    key={option.value}                    className={cn(                      'flex items-center justify-center mb-4 w-[calc((100%-8px)/2)] h-8 rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg cursor-pointer system-sm-medium text-text-secondary',                      value.reranking_mode === RerankingModeEnum.WeightedScore && option.value === RerankingModeEnum.WeightedScore && 'border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary',                      value.reranking_mode !== RerankingModeEnum.WeightedScore && option.value !== RerankingModeEnum.WeightedScore && 'border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary',                    )}                    onClick={() => handleChangeRerankMode(option.value)}                  >                    <div className='truncate'>{option.label}</div>                    <Tooltip                      popupContent={<div className='w-[200px]'>{option.tips}</div>}                      triggerClassName='ml-0.5 w-3.5 h-3.5'                    />                  </div>                ))              }            </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                  triggerClassName={`${!value.reranking_enable && '!opacity-60 !cursor-not-allowed'}`}                  defaultModel={rerankModel && { provider: rerankModel.provider_name, model: rerankModel.model_name }}                  modelList={rerankModelList}                  readonly={!value.reranking_enable}                  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)
 |