index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React, { useCallback } from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import cn from '@/utils/classnames'
  6. import TopKItem from '@/app/components/base/param-item/top-k-item'
  7. import ScoreThresholdItem from '@/app/components/base/param-item/score-threshold-item'
  8. import { RETRIEVE_METHOD } from '@/types/app'
  9. import Switch from '@/app/components/base/switch'
  10. import Tooltip from '@/app/components/base/tooltip'
  11. import type { RetrievalConfig } from '@/types/app'
  12. import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
  13. import { useCurrentProviderAndModel, useModelListAndDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
  14. import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
  15. import {
  16. DEFAULT_WEIGHTED_SCORE,
  17. RerankingModeEnum,
  18. WeightedScoreEnum,
  19. } from '@/models/datasets'
  20. import WeightedScore from '@/app/components/app/configuration/dataset-config/params-config/weighted-score'
  21. import Toast from '@/app/components/base/toast'
  22. type Props = {
  23. type: RETRIEVE_METHOD
  24. value: RetrievalConfig
  25. onChange: (value: RetrievalConfig) => void
  26. }
  27. const RetrievalParamConfig: FC<Props> = ({
  28. type,
  29. value,
  30. onChange,
  31. }) => {
  32. const { t } = useTranslation()
  33. const canToggleRerankModalEnable = type !== RETRIEVE_METHOD.hybrid
  34. const isEconomical = type === RETRIEVE_METHOD.invertedIndex
  35. const {
  36. defaultModel: rerankDefaultModel,
  37. modelList: rerankModelList,
  38. } = useModelListAndDefaultModel(ModelTypeEnum.rerank)
  39. const {
  40. currentModel,
  41. } = useCurrentProviderAndModel(
  42. rerankModelList,
  43. rerankDefaultModel
  44. ? {
  45. ...rerankDefaultModel,
  46. provider: rerankDefaultModel.provider.provider,
  47. }
  48. : undefined,
  49. )
  50. const handleDisabledSwitchClick = useCallback(() => {
  51. if (!currentModel)
  52. Toast.notify({ type: 'error', message: t('workflow.errorMsg.rerankModelRequired') })
  53. }, [currentModel, rerankDefaultModel, t])
  54. const isHybridSearch = type === RETRIEVE_METHOD.hybrid
  55. const rerankModel = (() => {
  56. if (value.reranking_model) {
  57. return {
  58. provider_name: value.reranking_model.reranking_provider_name,
  59. model_name: value.reranking_model.reranking_model_name,
  60. }
  61. }
  62. else if (rerankDefaultModel) {
  63. return {
  64. provider_name: rerankDefaultModel.provider.provider,
  65. model_name: rerankDefaultModel.model,
  66. }
  67. }
  68. })()
  69. const handleChangeRerankMode = (v: RerankingModeEnum) => {
  70. if (v === value.reranking_mode)
  71. return
  72. const result = {
  73. ...value,
  74. reranking_mode: v,
  75. }
  76. if (!result.weights && v === RerankingModeEnum.WeightedScore) {
  77. result.weights = {
  78. weight_type: WeightedScoreEnum.Customized,
  79. vector_setting: {
  80. vector_weight: DEFAULT_WEIGHTED_SCORE.other.semantic,
  81. embedding_provider_name: '',
  82. embedding_model_name: '',
  83. },
  84. keyword_setting: {
  85. keyword_weight: DEFAULT_WEIGHTED_SCORE.other.keyword,
  86. },
  87. }
  88. }
  89. onChange(result)
  90. }
  91. const rerankingModeOptions = [
  92. {
  93. value: RerankingModeEnum.WeightedScore,
  94. label: t('dataset.weightedScore.title'),
  95. tips: t('dataset.weightedScore.description'),
  96. },
  97. {
  98. value: RerankingModeEnum.RerankingModel,
  99. label: t('common.modelProvider.rerankModel.key'),
  100. tips: t('common.modelProvider.rerankModel.tip'),
  101. },
  102. ]
  103. return (
  104. <div>
  105. {!isEconomical && !isHybridSearch && (
  106. <div>
  107. <div className='flex h-8 items-center text-[13px] font-medium text-gray-900 space-x-2'>
  108. {canToggleRerankModalEnable && (
  109. <div
  110. className='flex items-center'
  111. onClick={handleDisabledSwitchClick}
  112. >
  113. <Switch
  114. size='md'
  115. defaultValue={currentModel ? value.reranking_enable : false}
  116. onChange={(v) => {
  117. onChange({
  118. ...value,
  119. reranking_enable: v,
  120. })
  121. }}
  122. disabled={!currentModel}
  123. />
  124. </div>
  125. )}
  126. <div className='flex items-center'>
  127. <span className='mr-0.5'>{t('common.modelProvider.rerankModel.key')}</span>
  128. <Tooltip
  129. popupContent={
  130. <div className="w-[200px]">{t('common.modelProvider.rerankModel.tip')}</div>
  131. }
  132. />
  133. </div>
  134. </div>
  135. <ModelSelector
  136. triggerClassName={`${!value.reranking_enable && '!opacity-60 !cursor-not-allowed'}`}
  137. defaultModel={rerankModel && { provider: rerankModel.provider_name, model: rerankModel.model_name }}
  138. modelList={rerankModelList}
  139. readonly={!value.reranking_enable}
  140. onSelect={(v) => {
  141. onChange({
  142. ...value,
  143. reranking_model: {
  144. reranking_provider_name: v.provider,
  145. reranking_model_name: v.model,
  146. },
  147. })
  148. }}
  149. />
  150. </div>
  151. )}
  152. {
  153. !isHybridSearch && (
  154. <div className={cn(!isEconomical && 'mt-4', 'flex space-between space-x-6')}>
  155. <TopKItem
  156. className='grow'
  157. value={value.top_k}
  158. onChange={(_key, v) => {
  159. onChange({
  160. ...value,
  161. top_k: v,
  162. })
  163. }}
  164. enable={true}
  165. />
  166. {(!isEconomical && !(value.search_method === RETRIEVE_METHOD.fullText && !value.reranking_enable)) && (
  167. <ScoreThresholdItem
  168. className='grow'
  169. value={value.score_threshold}
  170. onChange={(_key, v) => {
  171. onChange({
  172. ...value,
  173. score_threshold: v,
  174. })
  175. }}
  176. enable={value.score_threshold_enabled}
  177. hasSwitch={true}
  178. onSwitchChange={(_key, v) => {
  179. onChange({
  180. ...value,
  181. score_threshold_enabled: v,
  182. })
  183. }}
  184. />
  185. )}
  186. </div>
  187. )
  188. }
  189. {
  190. isHybridSearch && (
  191. <>
  192. <div className='flex items-center justify-between'>
  193. {
  194. rerankingModeOptions.map(option => (
  195. <div
  196. key={option.value}
  197. className={cn(
  198. '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',
  199. 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',
  200. 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',
  201. )}
  202. onClick={() => handleChangeRerankMode(option.value)}
  203. >
  204. <div className='truncate'>{option.label}</div>
  205. <Tooltip
  206. popupContent={<div className='w-[200px]'>{option.tips}</div>}
  207. triggerClassName='ml-0.5 w-3.5 h-3.5'
  208. />
  209. </div>
  210. ))
  211. }
  212. </div>
  213. {
  214. value.reranking_mode === RerankingModeEnum.WeightedScore && (
  215. <WeightedScore
  216. value={{
  217. value: [
  218. value.weights!.vector_setting.vector_weight,
  219. value.weights!.keyword_setting.keyword_weight,
  220. ],
  221. }}
  222. onChange={(v) => {
  223. onChange({
  224. ...value,
  225. weights: {
  226. ...value.weights!,
  227. vector_setting: {
  228. ...value.weights!.vector_setting,
  229. vector_weight: v.value[0],
  230. },
  231. keyword_setting: {
  232. ...value.weights!.keyword_setting,
  233. keyword_weight: v.value[1],
  234. },
  235. },
  236. })
  237. }}
  238. />
  239. )
  240. }
  241. {
  242. value.reranking_mode !== RerankingModeEnum.WeightedScore && (
  243. <ModelSelector
  244. triggerClassName={`${!value.reranking_enable && '!opacity-60 !cursor-not-allowed'}`}
  245. defaultModel={rerankModel && { provider: rerankModel.provider_name, model: rerankModel.model_name }}
  246. modelList={rerankModelList}
  247. readonly={!value.reranking_enable}
  248. onSelect={(v) => {
  249. onChange({
  250. ...value,
  251. reranking_model: {
  252. reranking_provider_name: v.provider,
  253. reranking_model_name: v.model,
  254. },
  255. })
  256. }}
  257. />
  258. )
  259. }
  260. <div className={cn(!isEconomical && 'mt-4', 'flex space-between space-x-6')}>
  261. <TopKItem
  262. className='grow'
  263. value={value.top_k}
  264. onChange={(_key, v) => {
  265. onChange({
  266. ...value,
  267. top_k: v,
  268. })
  269. }}
  270. enable={true}
  271. />
  272. <ScoreThresholdItem
  273. className='grow'
  274. value={value.score_threshold}
  275. onChange={(_key, v) => {
  276. onChange({
  277. ...value,
  278. score_threshold: v,
  279. })
  280. }}
  281. enable={value.score_threshold_enabled}
  282. hasSwitch={true}
  283. onSwitchChange={(_key, v) => {
  284. onChange({
  285. ...value,
  286. score_threshold_enabled: v,
  287. })
  288. }}
  289. />
  290. </div>
  291. </>
  292. )
  293. }
  294. </div>
  295. )
  296. }
  297. export default React.memo(RetrievalParamConfig)