You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

use-single-run-form-params.ts 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. import type { MutableRefObject } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form'
  4. import type { InputVar, PromptItem, Var, Variable } from '@/app/components/workflow/types'
  5. import { InputVarType, VarType } from '@/app/components/workflow/types'
  6. import type { LLMNodeType } from './types'
  7. import { EditionType } from '../../types'
  8. import useNodeCrud from '../_base/hooks/use-node-crud'
  9. import { useIsChatMode } from '../../hooks'
  10. import { useCallback } from 'react'
  11. import useConfigVision from '../../hooks/use-config-vision'
  12. import { noop } from 'lodash-es'
  13. import { findVariableWhenOnLLMVision } from '../utils'
  14. import useAvailableVarList from '../_base/hooks/use-available-var-list'
  15. const i18nPrefix = 'workflow.nodes.llm'
  16. type Params = {
  17. id: string,
  18. payload: LLMNodeType,
  19. runInputData: Record<string, any>
  20. runInputDataRef: MutableRefObject<Record<string, any>>
  21. getInputVars: (textList: string[]) => InputVar[]
  22. setRunInputData: (data: Record<string, any>) => void
  23. toVarInputs: (variables: Variable[]) => InputVar[]
  24. }
  25. const useSingleRunFormParams = ({
  26. id,
  27. payload,
  28. runInputData,
  29. runInputDataRef,
  30. getInputVars,
  31. setRunInputData,
  32. toVarInputs,
  33. }: Params) => {
  34. const { t } = useTranslation()
  35. const { inputs } = useNodeCrud<LLMNodeType>(id, payload)
  36. const getVarInputs = getInputVars
  37. const isChatMode = useIsChatMode()
  38. const contexts = runInputData['#context#']
  39. const setContexts = useCallback((newContexts: string[]) => {
  40. setRunInputData?.({
  41. ...runInputDataRef.current,
  42. '#context#': newContexts,
  43. })
  44. }, [runInputDataRef, setRunInputData])
  45. const visionFiles = runInputData['#files#']
  46. const setVisionFiles = useCallback((newFiles: any[]) => {
  47. setRunInputData?.({
  48. ...runInputDataRef.current,
  49. '#files#': newFiles,
  50. })
  51. }, [runInputDataRef, setRunInputData])
  52. // model
  53. const model = inputs.model
  54. const modelMode = inputs.model?.mode
  55. const isChatModel = modelMode === 'chat'
  56. const {
  57. isVisionModel,
  58. } = useConfigVision(model, {
  59. payload: inputs.vision,
  60. onChange: noop,
  61. })
  62. const isShowVars = (() => {
  63. if (isChatModel)
  64. return (inputs.prompt_template as PromptItem[]).some(item => item.edition_type === EditionType.jinja2)
  65. return (inputs.prompt_template as PromptItem).edition_type === EditionType.jinja2
  66. })()
  67. const filterMemoryPromptVar = useCallback((varPayload: Var) => {
  68. return [VarType.arrayObject, VarType.array, VarType.number, VarType.string, VarType.secret, VarType.arrayString, VarType.arrayNumber, VarType.file, VarType.arrayFile].includes(varPayload.type)
  69. }, [])
  70. const {
  71. availableVars,
  72. } = useAvailableVarList(id, {
  73. onlyLeafNodeVar: false,
  74. filterVar: filterMemoryPromptVar,
  75. })
  76. const allVarStrArr = (() => {
  77. const arr = isChatModel ? (inputs.prompt_template as PromptItem[]).filter(item => item.edition_type !== EditionType.jinja2).map(item => item.text) : [(inputs.prompt_template as PromptItem).text]
  78. if (isChatMode && isChatModel && !!inputs.memory) {
  79. arr.push('{{#sys.query#}}')
  80. arr.push(inputs.memory.query_prompt_template)
  81. }
  82. return arr
  83. })()
  84. const varInputs = (() => {
  85. const vars = getVarInputs(allVarStrArr) || []
  86. if (isShowVars)
  87. return [...vars, ...(toVarInputs ? (toVarInputs(inputs.prompt_config?.jinja2_variables || [])) : [])]
  88. return vars
  89. })()
  90. const inputVarValues = (() => {
  91. const vars: Record<string, any> = {}
  92. Object.keys(runInputData)
  93. .filter(key => !['#context#', '#files#'].includes(key))
  94. .forEach((key) => {
  95. vars[key] = runInputData[key]
  96. })
  97. return vars
  98. })()
  99. const setInputVarValues = useCallback((newPayload: Record<string, any>) => {
  100. const newVars = {
  101. ...newPayload,
  102. '#context#': runInputDataRef.current['#context#'],
  103. '#files#': runInputDataRef.current['#files#'],
  104. }
  105. setRunInputData?.(newVars)
  106. }, [runInputDataRef, setRunInputData])
  107. const forms = (() => {
  108. const forms: FormProps[] = []
  109. if (varInputs.length > 0) {
  110. forms.push(
  111. {
  112. label: t(`${i18nPrefix}.singleRun.variable`)!,
  113. inputs: varInputs,
  114. values: inputVarValues,
  115. onChange: setInputVarValues,
  116. },
  117. )
  118. }
  119. if (inputs.context?.variable_selector && inputs.context?.variable_selector.length > 0) {
  120. forms.push(
  121. {
  122. label: t(`${i18nPrefix}.context`)!,
  123. inputs: [{
  124. label: '',
  125. variable: '#context#',
  126. type: InputVarType.contexts,
  127. required: false,
  128. }],
  129. values: { '#context#': contexts },
  130. onChange: keyValue => setContexts(keyValue['#context#']),
  131. },
  132. )
  133. }
  134. if (isVisionModel && payload.vision?.enabled && payload.vision?.configs?.variable_selector) {
  135. const currentVariable = findVariableWhenOnLLMVision(payload.vision.configs.variable_selector, availableVars)
  136. forms.push(
  137. {
  138. label: t(`${i18nPrefix}.vision`)!,
  139. inputs: [{
  140. label: currentVariable?.variable as any,
  141. variable: '#files#',
  142. type: currentVariable?.formType as any,
  143. required: false,
  144. }],
  145. values: { '#files#': visionFiles },
  146. onChange: keyValue => setVisionFiles((keyValue as any)['#files#']),
  147. },
  148. )
  149. }
  150. return forms
  151. })()
  152. const getDependentVars = () => {
  153. const promptVars = varInputs.map(item => item.variable.slice(1, -1).split('.'))
  154. const contextVar = payload.context.variable_selector
  155. const vars = [...promptVars, contextVar]
  156. if (isVisionModel && payload.vision?.enabled && payload.vision?.configs?.variable_selector) {
  157. const visionVar = payload.vision.configs.variable_selector
  158. vars.push(visionVar)
  159. }
  160. return vars
  161. }
  162. const getDependentVar = (variable: string) => {
  163. if(variable === '#context#')
  164. return payload.context.variable_selector
  165. if(variable === '#files#')
  166. return payload.vision.configs?.variable_selector
  167. return false
  168. }
  169. return {
  170. forms,
  171. getDependentVars,
  172. getDependentVar,
  173. }
  174. }
  175. export default useSingleRunFormParams