index.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React from 'react'
  4. import { useContext } from 'use-context-selector'
  5. import produce from 'immer'
  6. import {
  7. RiAddLine,
  8. } from '@remixicon/react'
  9. import { useTranslation } from 'react-i18next'
  10. import SimplePromptInput from './simple-prompt-input'
  11. import AdvancedMessageInput from '@/app/components/app/configuration/config-prompt/advanced-prompt-input'
  12. import { PromptRole } from '@/models/debug'
  13. import type { PromptItem, PromptVariable } from '@/models/debug'
  14. import { type AppType, ModelModeType } from '@/types/app'
  15. import ConfigContext from '@/context/debug-configuration'
  16. import { MAX_PROMPT_MESSAGE_LENGTH } from '@/config'
  17. export type IPromptProps = {
  18. mode: AppType
  19. promptTemplate: string
  20. promptVariables: PromptVariable[]
  21. readonly?: boolean
  22. noTitle?: boolean
  23. gradientBorder?: boolean
  24. editorHeight?: number
  25. noResize?: boolean
  26. onChange?: (prompt: string, promptVariables: PromptVariable[]) => void
  27. }
  28. const Prompt: FC<IPromptProps> = ({
  29. mode,
  30. promptTemplate,
  31. promptVariables,
  32. noTitle,
  33. gradientBorder,
  34. readonly = false,
  35. editorHeight,
  36. noResize,
  37. onChange,
  38. }) => {
  39. const { t } = useTranslation()
  40. const {
  41. isAdvancedMode,
  42. currentAdvancedPrompt,
  43. setCurrentAdvancedPrompt,
  44. modelModeType,
  45. dataSets,
  46. hasSetBlockStatus,
  47. } = useContext(ConfigContext)
  48. const handleMessageTypeChange = (index: number, role: PromptRole) => {
  49. const newPrompt = produce(currentAdvancedPrompt as PromptItem[], (draft) => {
  50. draft[index].role = role
  51. })
  52. setCurrentAdvancedPrompt(newPrompt)
  53. }
  54. const handleValueChange = (value: string, index?: number) => {
  55. if (modelModeType === ModelModeType.chat) {
  56. const newPrompt = produce(currentAdvancedPrompt as PromptItem[], (draft) => {
  57. draft[index as number].text = value
  58. })
  59. setCurrentAdvancedPrompt(newPrompt, true)
  60. }
  61. else {
  62. const prompt = currentAdvancedPrompt as PromptItem
  63. setCurrentAdvancedPrompt({
  64. ...prompt,
  65. text: value,
  66. }, true)
  67. }
  68. }
  69. const handleAddMessage = () => {
  70. const currentAdvancedPromptList = currentAdvancedPrompt as PromptItem[]
  71. if (currentAdvancedPromptList.length === 0) {
  72. setCurrentAdvancedPrompt([{
  73. role: PromptRole.system,
  74. text: '',
  75. }])
  76. return
  77. }
  78. const lastMessageType = currentAdvancedPromptList[currentAdvancedPromptList.length - 1]?.role
  79. const appendMessage = {
  80. role: lastMessageType === PromptRole.user ? PromptRole.assistant : PromptRole.user,
  81. text: '',
  82. }
  83. setCurrentAdvancedPrompt([...currentAdvancedPromptList, appendMessage])
  84. }
  85. const handlePromptDelete = (index: number) => {
  86. const currentAdvancedPromptList = currentAdvancedPrompt as PromptItem[]
  87. const newPrompt = produce(currentAdvancedPromptList, (draft) => {
  88. draft.splice(index, 1)
  89. })
  90. setCurrentAdvancedPrompt(newPrompt)
  91. }
  92. const isContextMissing = dataSets.length > 0 && !hasSetBlockStatus.context
  93. const [isHideContextMissTip, setIsHideContextMissTip] = React.useState(false)
  94. if (!isAdvancedMode) {
  95. return (
  96. <SimplePromptInput
  97. mode={mode}
  98. promptTemplate={promptTemplate}
  99. promptVariables={promptVariables}
  100. readonly={readonly}
  101. onChange={onChange}
  102. noTitle={noTitle}
  103. gradientBorder={gradientBorder}
  104. editorHeight={editorHeight}
  105. noResize={noResize}
  106. />
  107. )
  108. }
  109. return (
  110. <div>
  111. <div className='space-y-3'>
  112. {modelModeType === ModelModeType.chat
  113. ? (
  114. (currentAdvancedPrompt as PromptItem[]).map((item, index) => (
  115. <AdvancedMessageInput
  116. key={index}
  117. isChatMode
  118. type={item.role as PromptRole}
  119. value={item.text}
  120. onTypeChange={type => handleMessageTypeChange(index, type)}
  121. canDelete={(currentAdvancedPrompt as PromptItem[]).length > 1}
  122. onDelete={() => handlePromptDelete(index)}
  123. onChange={value => handleValueChange(value, index)}
  124. promptVariables={promptVariables}
  125. isContextMissing={isContextMissing && !isHideContextMissTip}
  126. onHideContextMissingTip={() => setIsHideContextMissTip(true)}
  127. noResize={noResize}
  128. />
  129. ))
  130. )
  131. : (
  132. <AdvancedMessageInput
  133. type={(currentAdvancedPrompt as PromptItem).role as PromptRole}
  134. isChatMode={false}
  135. value={(currentAdvancedPrompt as PromptItem).text}
  136. onTypeChange={type => handleMessageTypeChange(0, type)}
  137. canDelete={false}
  138. onDelete={() => handlePromptDelete(0)}
  139. onChange={value => handleValueChange(value)}
  140. promptVariables={promptVariables}
  141. isContextMissing={isContextMissing && !isHideContextMissTip}
  142. onHideContextMissingTip={() => setIsHideContextMissTip(true)}
  143. noResize={noResize}
  144. />
  145. )
  146. }
  147. </div>
  148. {(modelModeType === ModelModeType.chat && (currentAdvancedPrompt as PromptItem[]).length < MAX_PROMPT_MESSAGE_LENGTH) && (
  149. <div
  150. onClick={handleAddMessage}
  151. className='mt-3 flex items-center h-8 justify-center bg-gray-50 rounded-lg cursor-pointer text-[13px] font-medium text-gray-700 space-x-2'>
  152. <RiAddLine className='w-4 h-4' />
  153. <div>{t('appDebug.promptMode.operation.addMessage')}</div>
  154. </div>
  155. )}
  156. </div>
  157. )
  158. }
  159. export default React.memo(Prompt)