use-config.ts 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. import { useCallback, useEffect, useRef, useState } from 'react'
  2. import produce from 'immer'
  3. import type { Memory, MoreInfo, ValueSelector, Var } from '../../types'
  4. import { ChangeType, VarType } from '../../types'
  5. import { useStore } from '../../store'
  6. import {
  7. useIsChatMode,
  8. useNodesReadOnly,
  9. useWorkflow,
  10. } from '../../hooks'
  11. import useOneStepRun from '../_base/hooks/use-one-step-run'
  12. import useConfigVision from '../../hooks/use-config-vision'
  13. import type { Param, ParameterExtractorNodeType, ReasoningModeType } from './types'
  14. import { useModelListAndDefaultModelAndCurrentProviderAndModel, useTextGenerationCurrentProviderAndModelAndModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
  15. import {
  16. ModelFeatureEnum,
  17. ModelTypeEnum,
  18. } from '@/app/components/header/account-setting/model-provider-page/declarations'
  19. import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
  20. import { checkHasQueryBlock } from '@/app/components/base/prompt-editor/constants'
  21. import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list'
  22. const useConfig = (id: string, payload: ParameterExtractorNodeType) => {
  23. const { nodesReadOnly: readOnly } = useNodesReadOnly()
  24. const { handleOutVarRenameChange } = useWorkflow()
  25. const isChatMode = useIsChatMode()
  26. const defaultConfig = useStore(s => s.nodesDefaultConfigs)[payload.type]
  27. const [defaultRolePrefix, setDefaultRolePrefix] = useState<{ user: string; assistant: string }>({ user: '', assistant: '' })
  28. const { inputs, setInputs: doSetInputs } = useNodeCrud<ParameterExtractorNodeType>(id, payload)
  29. const inputRef = useRef(inputs)
  30. const setInputs = useCallback((newInputs: ParameterExtractorNodeType) => {
  31. if (newInputs.memory && !newInputs.memory.role_prefix) {
  32. const newPayload = produce(newInputs, (draft) => {
  33. draft.memory!.role_prefix = defaultRolePrefix
  34. })
  35. doSetInputs(newPayload)
  36. inputRef.current = newPayload
  37. return
  38. }
  39. doSetInputs(newInputs)
  40. inputRef.current = newInputs
  41. }, [doSetInputs, defaultRolePrefix])
  42. const filterVar = useCallback((varPayload: Var) => {
  43. return [VarType.string].includes(varPayload.type)
  44. }, [])
  45. const handleInputVarChange = useCallback((newInputVar: ValueSelector | string) => {
  46. const newInputs = produce(inputs, (draft) => {
  47. draft.query = newInputVar as ValueSelector || []
  48. })
  49. setInputs(newInputs)
  50. }, [inputs, setInputs])
  51. const handleExactParamsChange = useCallback((newParams: Param[], moreInfo?: MoreInfo) => {
  52. const newInputs = produce(inputs, (draft) => {
  53. draft.parameters = newParams
  54. })
  55. setInputs(newInputs)
  56. if (moreInfo && moreInfo?.type === ChangeType.changeVarName && moreInfo.payload)
  57. handleOutVarRenameChange(id, [id, moreInfo.payload.beforeKey], [id, moreInfo.payload.afterKey!])
  58. }, [handleOutVarRenameChange, id, inputs, setInputs])
  59. const addExtractParameter = useCallback((payload: Param) => {
  60. const newInputs = produce(inputs, (draft) => {
  61. if (!draft.parameters)
  62. draft.parameters = []
  63. draft.parameters.push(payload)
  64. })
  65. setInputs(newInputs)
  66. }, [inputs, setInputs])
  67. // model
  68. const model = inputs.model || {
  69. provider: '',
  70. name: '',
  71. mode: 'chat',
  72. completion_params: {
  73. temperature: 0.7,
  74. },
  75. }
  76. const modelMode = inputs.model?.mode
  77. const isChatModel = modelMode === 'chat'
  78. const isCompletionModel = !isChatModel
  79. const {
  80. isVisionModel,
  81. handleVisionResolutionEnabledChange,
  82. handleVisionResolutionChange,
  83. handleModelChanged: handleVisionConfigAfterModelChanged,
  84. } = useConfigVision(model, {
  85. payload: inputs.vision,
  86. onChange: (newPayload) => {
  87. const newInputs = produce(inputs, (draft) => {
  88. draft.vision = newPayload
  89. })
  90. setInputs(newInputs)
  91. },
  92. })
  93. const appendDefaultPromptConfig = useCallback((draft: ParameterExtractorNodeType, defaultConfig: any, _passInIsChatMode?: boolean) => {
  94. const promptTemplates = defaultConfig.prompt_templates
  95. if (!isChatModel) {
  96. setDefaultRolePrefix({
  97. user: promptTemplates.completion_model.conversation_histories_role.user_prefix,
  98. assistant: promptTemplates.completion_model.conversation_histories_role.assistant_prefix,
  99. })
  100. }
  101. }, [isChatModel])
  102. const [modelChanged, setModelChanged] = useState(false)
  103. const {
  104. currentProvider,
  105. currentModel,
  106. } = useModelListAndDefaultModelAndCurrentProviderAndModel(ModelTypeEnum.textGeneration)
  107. const handleModelChanged = useCallback((model: { provider: string; modelId: string; mode?: string }) => {
  108. const newInputs = produce(inputRef.current, (draft) => {
  109. draft.model.provider = model.provider
  110. draft.model.name = model.modelId
  111. draft.model.mode = model.mode!
  112. const isModeChange = model.mode !== inputRef.current.model?.mode
  113. if (isModeChange && defaultConfig && Object.keys(defaultConfig).length > 0)
  114. appendDefaultPromptConfig(draft, defaultConfig, model.mode === 'chat')
  115. })
  116. setInputs(newInputs)
  117. setModelChanged(true)
  118. }, [setInputs, defaultConfig, appendDefaultPromptConfig])
  119. useEffect(() => {
  120. if (currentProvider?.provider && currentModel?.model && !model.provider) {
  121. handleModelChanged({
  122. provider: currentProvider?.provider,
  123. modelId: currentModel?.model,
  124. mode: currentModel?.model_properties?.mode as string,
  125. })
  126. }
  127. }, [model?.provider, currentProvider, currentModel, handleModelChanged])
  128. // change to vision model to set vision enabled, else disabled
  129. useEffect(() => {
  130. if (!modelChanged)
  131. return
  132. setModelChanged(false)
  133. handleVisionConfigAfterModelChanged()
  134. // eslint-disable-next-line react-hooks/exhaustive-deps
  135. }, [isVisionModel, modelChanged])
  136. const {
  137. currentModel: currModel,
  138. } = useTextGenerationCurrentProviderAndModelAndModelList(
  139. {
  140. provider: model.provider,
  141. model: model.name,
  142. },
  143. )
  144. const isSupportFunctionCall = currModel?.features?.includes(ModelFeatureEnum.toolCall) || currModel?.features?.includes(ModelFeatureEnum.multiToolCall)
  145. const filterInputVar = useCallback((varPayload: Var) => {
  146. return [VarType.number, VarType.string].includes(varPayload.type)
  147. }, [])
  148. const {
  149. availableVars,
  150. availableNodesWithParent,
  151. } = useAvailableVarList(id, {
  152. onlyLeafNodeVar: false,
  153. filterVar: filterInputVar,
  154. })
  155. const handleCompletionParamsChange = useCallback((newParams: Record<string, any>) => {
  156. const newInputs = produce(inputs, (draft) => {
  157. draft.model.completion_params = newParams
  158. })
  159. setInputs(newInputs)
  160. }, [inputs, setInputs])
  161. const handleInstructionChange = useCallback((newInstruction: string) => {
  162. const newInputs = produce(inputs, (draft) => {
  163. draft.instruction = newInstruction
  164. })
  165. setInputs(newInputs)
  166. }, [inputs, setInputs])
  167. const hasSetBlockStatus = {
  168. history: false,
  169. query: isChatMode ? checkHasQueryBlock(inputs.instruction) : false,
  170. context: false,
  171. }
  172. const handleMemoryChange = useCallback((newMemory?: Memory) => {
  173. const newInputs = produce(inputs, (draft) => {
  174. draft.memory = newMemory
  175. })
  176. setInputs(newInputs)
  177. }, [inputs, setInputs])
  178. const handleReasoningModeChange = useCallback((newReasoningMode: ReasoningModeType) => {
  179. const newInputs = produce(inputs, (draft) => {
  180. draft.reasoning_mode = newReasoningMode
  181. })
  182. setInputs(newInputs)
  183. }, [inputs, setInputs])
  184. const handleImportFromTool = useCallback((params: Param[]) => {
  185. const newInputs = produce(inputs, (draft) => {
  186. draft.parameters = params
  187. })
  188. setInputs(newInputs)
  189. }, [inputs, setInputs])
  190. // single run
  191. const {
  192. isShowSingleRun,
  193. hideSingleRun,
  194. getInputVars,
  195. runningStatus,
  196. handleRun,
  197. handleStop,
  198. runInputData,
  199. setRunInputData,
  200. runResult,
  201. } = useOneStepRun<ParameterExtractorNodeType>({
  202. id,
  203. data: inputs,
  204. defaultRunInputData: {
  205. query: '',
  206. },
  207. })
  208. const varInputs = getInputVars([inputs.instruction])
  209. const inputVarValues = (() => {
  210. const vars: Record<string, any> = {}
  211. Object.keys(runInputData)
  212. .forEach((key) => {
  213. vars[key] = runInputData[key]
  214. })
  215. return vars
  216. })()
  217. const setInputVarValues = useCallback((newPayload: Record<string, any>) => {
  218. setRunInputData(newPayload)
  219. }, [setRunInputData])
  220. return {
  221. readOnly,
  222. handleInputVarChange,
  223. filterVar,
  224. isChatMode,
  225. inputs,
  226. isChatModel,
  227. isCompletionModel,
  228. handleModelChanged,
  229. handleCompletionParamsChange,
  230. handleImportFromTool,
  231. handleExactParamsChange,
  232. addExtractParameter,
  233. handleInstructionChange,
  234. hasSetBlockStatus,
  235. availableVars,
  236. availableNodesWithParent,
  237. isSupportFunctionCall,
  238. handleReasoningModeChange,
  239. handleMemoryChange,
  240. varInputs,
  241. inputVarValues,
  242. isVisionModel,
  243. handleVisionResolutionEnabledChange,
  244. handleVisionResolutionChange,
  245. isShowSingleRun,
  246. hideSingleRun,
  247. runningStatus,
  248. handleRun,
  249. handleStop,
  250. runResult,
  251. setInputVarValues,
  252. }
  253. }
  254. export default useConfig