chat-user-input.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import React from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import { useContext } from 'use-context-selector'
  4. import ConfigContext from '@/context/debug-configuration'
  5. import Input from '@/app/components/base/input'
  6. import Select from '@/app/components/base/select'
  7. import Textarea from '@/app/components/base/textarea'
  8. import { DEFAULT_VALUE_MAX_LEN } from '@/config'
  9. import type { Inputs } from '@/models/debug'
  10. import cn from '@/utils/classnames'
  11. type Props = {
  12. inputs: Inputs
  13. }
  14. const ChatUserInput = ({
  15. inputs,
  16. }: Props) => {
  17. const { t } = useTranslation()
  18. const { modelConfig, setInputs } = useContext(ConfigContext)
  19. const promptVariables = modelConfig.configs.prompt_variables.filter(({ key, name }) => {
  20. return key && key?.trim() && name && name?.trim()
  21. })
  22. const promptVariableObj = (() => {
  23. const obj: Record<string, boolean> = {}
  24. promptVariables.forEach((input) => {
  25. obj[input.key] = true
  26. })
  27. return obj
  28. })()
  29. const handleInputValueChange = (key: string, value: string) => {
  30. if (!(key in promptVariableObj))
  31. return
  32. const newInputs = { ...inputs }
  33. promptVariables.forEach((input) => {
  34. if (input.key === key)
  35. newInputs[key] = value
  36. })
  37. setInputs(newInputs)
  38. }
  39. if (!promptVariables.length)
  40. return null
  41. return (
  42. <div className={cn('bg-components-panel-on-panel-item-bg rounded-xl border-[0.5px] border-components-panel-border-subtle shadow-xs z-[1]')}>
  43. <div className='px-4 pt-3 pb-4'>
  44. {promptVariables.map(({ key, name, type, options, max_length, required }, index) => (
  45. <div
  46. key={key}
  47. className='mb-4 last-of-type:mb-0'
  48. >
  49. <div>
  50. <div className='h-6 mb-1 flex items-center gap-1 text-text-secondary system-sm-semibold'>
  51. <div className='truncate'>{name || key}</div>
  52. {!required && <span className='text-text-tertiary system-xs-regular'>{t('workflow.panel.optional')}</span>}
  53. </div>
  54. <div className='grow'>
  55. {type === 'string' && (
  56. <Input
  57. value={inputs[key] ? `${inputs[key]}` : ''}
  58. onChange={(e) => { handleInputValueChange(key, e.target.value) }}
  59. placeholder={name}
  60. autoFocus={index === 0}
  61. maxLength={max_length || DEFAULT_VALUE_MAX_LEN}
  62. />
  63. )}
  64. {type === 'paragraph' && (
  65. <Textarea
  66. className='grow h-[120px]'
  67. placeholder={name}
  68. value={inputs[key] ? `${inputs[key]}` : ''}
  69. onChange={(e) => { handleInputValueChange(key, e.target.value) }}
  70. />
  71. )}
  72. {type === 'select' && (
  73. <Select
  74. className='w-full'
  75. defaultValue={inputs[key] as string}
  76. onSelect={(i) => { handleInputValueChange(key, i.value as string) }}
  77. items={(options || []).map(i => ({ name: i, value: i }))}
  78. allowSearch={false}
  79. bgClassName='bg-gray-50'
  80. />
  81. )}
  82. {type === 'number' && (
  83. <Input
  84. type='number'
  85. value={inputs[key] ? `${inputs[key]}` : ''}
  86. onChange={(e) => { handleInputValueChange(key, e.target.value) }}
  87. placeholder={name}
  88. autoFocus={index === 0}
  89. maxLength={max_length || DEFAULT_VALUE_MAX_LEN}
  90. />
  91. )}
  92. </div>
  93. </div>
  94. </div>
  95. ))}
  96. </div>
  97. </div>
  98. )
  99. }
  100. export default ChatUserInput