use-config.ts 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. import { useCallback, useEffect, useRef, useState } from 'react'
  2. import produce from 'immer'
  3. import { isEqual } from 'lodash-es'
  4. import type { ValueSelector, Var } from '../../types'
  5. import { BlockEnum, VarType } from '../../types'
  6. import {
  7. useIsChatMode, useNodesReadOnly,
  8. useWorkflow,
  9. } from '../../hooks'
  10. import type { KnowledgeRetrievalNodeType, MultipleRetrievalConfig } from './types'
  11. import { RETRIEVE_TYPE } from '@/types/app'
  12. import { DATASET_DEFAULT } from '@/config'
  13. import type { DataSet } from '@/models/datasets'
  14. import { fetchDatasets } from '@/service/datasets'
  15. import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
  16. import useOneStepRun from '@/app/components/workflow/nodes/_base/hooks/use-one-step-run'
  17. import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
  18. import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
  19. const useConfig = (id: string, payload: KnowledgeRetrievalNodeType) => {
  20. const { nodesReadOnly: readOnly } = useNodesReadOnly()
  21. const isChatMode = useIsChatMode()
  22. const { getBeforeNodesInSameBranch } = useWorkflow()
  23. const startNode = getBeforeNodesInSameBranch(id).find(node => node.data.type === BlockEnum.Start)
  24. const startNodeId = startNode?.id
  25. const { inputs, setInputs: doSetInputs } = useNodeCrud<KnowledgeRetrievalNodeType>(id, payload)
  26. const setInputs = useCallback((s: KnowledgeRetrievalNodeType) => {
  27. const newInputs = produce(s, (draft) => {
  28. if (s.retrieval_mode === RETRIEVE_TYPE.multiWay)
  29. delete draft.single_retrieval_config
  30. else
  31. delete draft.multiple_retrieval_config
  32. })
  33. // not work in pass to draft...
  34. doSetInputs(newInputs)
  35. }, [doSetInputs])
  36. const inputRef = useRef(inputs)
  37. useEffect(() => {
  38. inputRef.current = inputs
  39. }, [inputs])
  40. const handleQueryVarChange = useCallback((newVar: ValueSelector | string) => {
  41. const newInputs = produce(inputs, (draft) => {
  42. draft.query_variable_selector = newVar as ValueSelector
  43. })
  44. setInputs(newInputs)
  45. }, [inputs, setInputs])
  46. const {
  47. currentProvider,
  48. currentModel,
  49. } = useModelListAndDefaultModelAndCurrentProviderAndModel(ModelTypeEnum.textGeneration)
  50. const {
  51. defaultModel: rerankDefaultModel,
  52. } = useModelListAndDefaultModelAndCurrentProviderAndModel(ModelTypeEnum.rerank)
  53. const handleModelChanged = useCallback((model: { provider: string; modelId: string; mode?: string }) => {
  54. const newInputs = produce(inputRef.current, (draft) => {
  55. if (!draft.single_retrieval_config) {
  56. draft.single_retrieval_config = {
  57. model: {
  58. provider: '',
  59. name: '',
  60. mode: '',
  61. completion_params: {},
  62. },
  63. }
  64. }
  65. const draftModel = draft.single_retrieval_config?.model
  66. draftModel.provider = model.provider
  67. draftModel.name = model.modelId
  68. draftModel.mode = model.mode!
  69. })
  70. setInputs(newInputs)
  71. }, [setInputs])
  72. const handleCompletionParamsChange = useCallback((newParams: Record<string, any>) => {
  73. // inputRef.current.single_retrieval_config?.model is old when change the provider...
  74. if (isEqual(newParams, inputRef.current.single_retrieval_config?.model.completion_params))
  75. return
  76. const newInputs = produce(inputRef.current, (draft) => {
  77. if (!draft.single_retrieval_config) {
  78. draft.single_retrieval_config = {
  79. model: {
  80. provider: '',
  81. name: '',
  82. mode: '',
  83. completion_params: {},
  84. },
  85. }
  86. }
  87. draft.single_retrieval_config.model.completion_params = newParams
  88. })
  89. setInputs(newInputs)
  90. }, [setInputs])
  91. // set defaults models
  92. useEffect(() => {
  93. const inputs = inputRef.current
  94. if (inputs.retrieval_mode === RETRIEVE_TYPE.multiWay && inputs.multiple_retrieval_config?.reranking_model?.provider)
  95. return
  96. if (inputs.retrieval_mode === RETRIEVE_TYPE.oneWay && inputs.single_retrieval_config?.model?.provider)
  97. return
  98. const newInput = produce(inputs, (draft) => {
  99. if (currentProvider?.provider && currentModel?.model) {
  100. const hasSetModel = draft.single_retrieval_config?.model?.provider
  101. if (!hasSetModel) {
  102. draft.single_retrieval_config = {
  103. model: {
  104. provider: currentProvider?.provider,
  105. name: currentModel?.model,
  106. mode: currentModel?.model_properties?.mode as string,
  107. completion_params: {},
  108. },
  109. }
  110. }
  111. }
  112. const multipleRetrievalConfig = draft.multiple_retrieval_config
  113. draft.multiple_retrieval_config = {
  114. top_k: multipleRetrievalConfig?.top_k || DATASET_DEFAULT.top_k,
  115. score_threshold: multipleRetrievalConfig?.score_threshold,
  116. reranking_model: payload.retrieval_mode === RETRIEVE_TYPE.oneWay
  117. ? undefined
  118. : (!multipleRetrievalConfig?.reranking_model?.provider
  119. ? {
  120. provider: rerankDefaultModel?.provider?.provider || '',
  121. model: rerankDefaultModel?.model || '',
  122. }
  123. : multipleRetrievalConfig?.reranking_model),
  124. }
  125. })
  126. setInputs(newInput)
  127. // eslint-disable-next-line react-hooks/exhaustive-deps
  128. }, [currentProvider?.provider, currentModel, rerankDefaultModel])
  129. const handleRetrievalModeChange = useCallback((newMode: RETRIEVE_TYPE) => {
  130. const newInputs = produce(inputs, (draft) => {
  131. draft.retrieval_mode = newMode
  132. if (newMode === RETRIEVE_TYPE.multiWay) {
  133. draft.multiple_retrieval_config = {
  134. top_k: draft.multiple_retrieval_config?.top_k || DATASET_DEFAULT.top_k,
  135. score_threshold: draft.multiple_retrieval_config?.score_threshold,
  136. reranking_model: !draft.multiple_retrieval_config?.reranking_model?.provider
  137. ? {
  138. provider: rerankDefaultModel?.provider?.provider || '',
  139. model: rerankDefaultModel?.model || '',
  140. }
  141. : draft.multiple_retrieval_config?.reranking_model,
  142. }
  143. }
  144. else {
  145. const hasSetModel = draft.single_retrieval_config?.model?.provider
  146. if (!hasSetModel) {
  147. draft.single_retrieval_config = {
  148. model: {
  149. provider: currentProvider?.provider || '',
  150. name: currentModel?.model || '',
  151. mode: currentModel?.model_properties?.mode as string,
  152. completion_params: {},
  153. },
  154. }
  155. }
  156. }
  157. })
  158. setInputs(newInputs)
  159. }, [currentModel?.model, currentModel?.model_properties?.mode, currentProvider?.provider, inputs, rerankDefaultModel?.model, rerankDefaultModel?.provider?.provider, setInputs])
  160. const handleMultipleRetrievalConfigChange = useCallback((newConfig: MultipleRetrievalConfig) => {
  161. const newInputs = produce(inputs, (draft) => {
  162. draft.multiple_retrieval_config = newConfig
  163. })
  164. setInputs(newInputs)
  165. }, [inputs, setInputs])
  166. // datasets
  167. const [selectedDatasets, setSelectedDatasets] = useState<DataSet[]>([])
  168. useEffect(() => {
  169. (async () => {
  170. const inputs = inputRef.current
  171. const datasetIds = inputs.dataset_ids
  172. if (datasetIds?.length > 0) {
  173. const { data: dataSetsWithDetail } = await fetchDatasets({ url: '/datasets', params: { page: 1, ids: datasetIds } })
  174. setSelectedDatasets(dataSetsWithDetail)
  175. }
  176. const newInputs = produce(inputs, (draft) => {
  177. draft.dataset_ids = datasetIds
  178. })
  179. setInputs(newInputs)
  180. })()
  181. // eslint-disable-next-line react-hooks/exhaustive-deps
  182. }, [])
  183. useEffect(() => {
  184. let query_variable_selector: ValueSelector = inputs.query_variable_selector
  185. if (isChatMode && inputs.query_variable_selector.length === 0 && startNodeId)
  186. query_variable_selector = [startNodeId, 'sys.query']
  187. setInputs({
  188. ...inputs,
  189. query_variable_selector,
  190. })
  191. // eslint-disable-next-line react-hooks/exhaustive-deps
  192. }, [])
  193. const handleOnDatasetsChange = useCallback((newDatasets: DataSet[]) => {
  194. const newInputs = produce(inputs, (draft) => {
  195. draft.dataset_ids = newDatasets.map(d => d.id)
  196. })
  197. setInputs(newInputs)
  198. setSelectedDatasets(newDatasets)
  199. }, [inputs, setInputs])
  200. const filterVar = useCallback((varPayload: Var) => {
  201. return varPayload.type === VarType.string
  202. }, [])
  203. // single run
  204. const {
  205. isShowSingleRun,
  206. hideSingleRun,
  207. runningStatus,
  208. handleRun,
  209. handleStop,
  210. runInputData,
  211. setRunInputData,
  212. runResult,
  213. } = useOneStepRun<KnowledgeRetrievalNodeType>({
  214. id,
  215. data: inputs,
  216. defaultRunInputData: {
  217. query: '',
  218. },
  219. })
  220. const query = runInputData.query
  221. const setQuery = useCallback((newQuery: string) => {
  222. setRunInputData({
  223. ...runInputData,
  224. query: newQuery,
  225. })
  226. }, [runInputData, setRunInputData])
  227. return {
  228. readOnly,
  229. inputs,
  230. handleQueryVarChange,
  231. filterVar,
  232. handleRetrievalModeChange,
  233. handleMultipleRetrievalConfigChange,
  234. handleModelChanged,
  235. handleCompletionParamsChange,
  236. selectedDatasets,
  237. handleOnDatasetsChange,
  238. isShowSingleRun,
  239. hideSingleRun,
  240. runningStatus,
  241. handleRun,
  242. handleStop,
  243. query,
  244. setQuery,
  245. runResult,
  246. }
  247. }
  248. export default useConfig