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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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, Var, Variable } from '@/app/components/workflow/types'
  5. import { InputVarType, VarType } from '@/app/components/workflow/types'
  6. import type { ParameterExtractorNodeType } from './types'
  7. import useNodeCrud from '../_base/hooks/use-node-crud'
  8. import { useCallback } from 'react'
  9. import useConfigVision from '../../hooks/use-config-vision'
  10. import { noop } from 'lodash-es'
  11. import { findVariableWhenOnLLMVision } from '../utils'
  12. import useAvailableVarList from '../_base/hooks/use-available-var-list'
  13. const i18nPrefix = 'workflow.nodes.parameterExtractor'
  14. type Params = {
  15. id: string,
  16. payload: ParameterExtractorNodeType,
  17. runInputData: Record<string, any>
  18. runInputDataRef: MutableRefObject<Record<string, any>>
  19. getInputVars: (textList: string[]) => InputVar[]
  20. setRunInputData: (data: Record<string, any>) => void
  21. toVarInputs: (variables: Variable[]) => InputVar[]
  22. }
  23. const useSingleRunFormParams = ({
  24. id,
  25. payload,
  26. runInputData,
  27. runInputDataRef,
  28. getInputVars,
  29. setRunInputData,
  30. }: Params) => {
  31. const { t } = useTranslation()
  32. const { inputs } = useNodeCrud<ParameterExtractorNodeType>(id, payload)
  33. const model = inputs.model
  34. const {
  35. isVisionModel,
  36. } = useConfigVision(model, {
  37. payload: inputs.vision,
  38. onChange: noop,
  39. })
  40. const visionFiles = runInputData['#files#']
  41. const setVisionFiles = useCallback((newFiles: any[]) => {
  42. setRunInputData?.({
  43. ...runInputDataRef.current,
  44. '#files#': newFiles,
  45. })
  46. }, [runInputDataRef, setRunInputData])
  47. const varInputs = getInputVars([inputs.instruction])
  48. const inputVarValues = (() => {
  49. const vars: Record<string, any> = {}
  50. Object.keys(runInputData)
  51. .filter(key => !['#context#', '#files#'].includes(key))
  52. .forEach((key) => {
  53. vars[key] = runInputData[key]
  54. })
  55. return vars
  56. })()
  57. const setInputVarValues = useCallback((newPayload: Record<string, any>) => {
  58. const newVars = {
  59. ...newPayload,
  60. '#context#': runInputDataRef.current['#context#'],
  61. '#files#': runInputDataRef.current['#files#'],
  62. }
  63. setRunInputData?.(newVars)
  64. }, [runInputDataRef, setRunInputData])
  65. const filterVisionInputVar = useCallback((varPayload: Var) => {
  66. return [VarType.file, VarType.arrayFile].includes(varPayload.type)
  67. }, [])
  68. const {
  69. availableVars: availableVisionVars,
  70. } = useAvailableVarList(id, {
  71. onlyLeafNodeVar: false,
  72. filterVar: filterVisionInputVar,
  73. })
  74. const forms = (() => {
  75. const forms: FormProps[] = []
  76. forms.push(
  77. {
  78. label: t('workflow.nodes.llm.singleRun.variable')!,
  79. inputs: [{
  80. label: t(`${i18nPrefix}.inputVar`)!,
  81. variable: 'query',
  82. type: InputVarType.paragraph,
  83. required: true,
  84. }, ...varInputs],
  85. values: inputVarValues,
  86. onChange: setInputVarValues,
  87. },
  88. )
  89. if (isVisionModel && payload.vision?.enabled && payload.vision?.configs?.variable_selector) {
  90. const currentVariable = findVariableWhenOnLLMVision(payload.vision.configs.variable_selector, availableVisionVars)
  91. forms.push(
  92. {
  93. label: t('workflow.nodes.llm.vision')!,
  94. inputs: [{
  95. label: currentVariable?.variable as any,
  96. variable: '#files#',
  97. type: currentVariable?.formType as any,
  98. required: false,
  99. }],
  100. values: { '#files#': visionFiles },
  101. onChange: keyValue => setVisionFiles((keyValue as any)['#files#']),
  102. },
  103. )
  104. }
  105. return forms
  106. })()
  107. const getDependentVars = () => {
  108. const promptVars = varInputs.map((item) => {
  109. // Guard against null/undefined variable to prevent app crash
  110. if (!item.variable || typeof item.variable !== 'string')
  111. return []
  112. return item.variable.slice(1, -1).split('.')
  113. }).filter(arr => arr.length > 0)
  114. const vars = [payload.query, ...promptVars]
  115. if (isVisionModel && payload.vision?.enabled && payload.vision?.configs?.variable_selector) {
  116. const visionVar = payload.vision.configs.variable_selector
  117. vars.push(visionVar)
  118. }
  119. return vars
  120. }
  121. const getDependentVar = (variable: string) => {
  122. if(variable === 'query')
  123. return payload.query
  124. if(variable === '#files#')
  125. return payload.vision.configs?.variable_selector
  126. return false
  127. }
  128. return {
  129. forms,
  130. getDependentVars,
  131. getDependentVar,
  132. }
  133. }
  134. export default useSingleRunFormParams