chat-item.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import type { FC } from 'react'
  2. import {
  3. memo,
  4. useCallback,
  5. useMemo,
  6. } from 'react'
  7. import type { ModelAndParameter } from '../types'
  8. import {
  9. APP_CHAT_WITH_MULTIPLE_MODEL,
  10. APP_CHAT_WITH_MULTIPLE_MODEL_RESTART,
  11. } from '../types'
  12. import {
  13. useConfigFromDebugContext,
  14. useFormattingChangedSubscription,
  15. } from '../hooks'
  16. import Chat from '@/app/components/base/chat/chat'
  17. import { useChat } from '@/app/components/base/chat/chat/hooks'
  18. import { useDebugConfigurationContext } from '@/context/debug-configuration'
  19. import type { OnSend } from '@/app/components/base/chat/types'
  20. import { useEventEmitterContextContext } from '@/context/event-emitter'
  21. import { useProviderContext } from '@/context/provider-context'
  22. import {
  23. fetchConversationMessages,
  24. fetchSuggestedQuestions,
  25. stopChatMessageResponding,
  26. } from '@/service/debug'
  27. import Avatar from '@/app/components/base/avatar'
  28. import { useAppContext } from '@/context/app-context'
  29. import { ModelFeatureEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
  30. type ChatItemProps = {
  31. modelAndParameter: ModelAndParameter
  32. }
  33. const ChatItem: FC<ChatItemProps> = ({
  34. modelAndParameter,
  35. }) => {
  36. const { userProfile } = useAppContext()
  37. const {
  38. modelConfig,
  39. appId,
  40. inputs,
  41. visionConfig,
  42. collectionList,
  43. } = useDebugConfigurationContext()
  44. const { textGenerationModelList } = useProviderContext()
  45. const config = useConfigFromDebugContext()
  46. const {
  47. chatList,
  48. chatListRef,
  49. isResponding,
  50. handleSend,
  51. suggestedQuestions,
  52. handleRestart,
  53. } = useChat(
  54. config,
  55. {
  56. inputs,
  57. promptVariables: modelConfig.configs.prompt_variables,
  58. },
  59. [],
  60. taskId => stopChatMessageResponding(appId, taskId),
  61. )
  62. useFormattingChangedSubscription(chatList)
  63. const doSend: OnSend = useCallback((message, files) => {
  64. const currentProvider = textGenerationModelList.find(item => item.provider === modelAndParameter.provider)
  65. const currentModel = currentProvider?.models.find(model => model.model === modelAndParameter.model)
  66. const supportVision = currentModel?.features?.includes(ModelFeatureEnum.vision)
  67. const configData = {
  68. ...config,
  69. model: {
  70. provider: modelAndParameter.provider,
  71. name: modelAndParameter.model,
  72. mode: currentModel?.model_properties.mode,
  73. completion_params: modelAndParameter.parameters,
  74. },
  75. }
  76. const data: any = {
  77. query: message,
  78. inputs,
  79. model_config: configData,
  80. parent_message_id: chatListRef.current.at(-1)?.id || null,
  81. }
  82. if (visionConfig.enabled && files?.length && supportVision)
  83. data.files = files
  84. handleSend(
  85. `apps/${appId}/chat-messages`,
  86. data,
  87. {
  88. onGetConversationMessages: (conversationId, getAbortController) => fetchConversationMessages(appId, conversationId, getAbortController),
  89. onGetSuggestedQuestions: (responseItemId, getAbortController) => fetchSuggestedQuestions(appId, responseItemId, getAbortController),
  90. },
  91. )
  92. }, [appId, config, handleSend, inputs, modelAndParameter, textGenerationModelList, visionConfig.enabled, chatListRef])
  93. const { eventEmitter } = useEventEmitterContextContext()
  94. eventEmitter?.useSubscription((v: any) => {
  95. if (v.type === APP_CHAT_WITH_MULTIPLE_MODEL)
  96. doSend(v.payload.message, v.payload.files)
  97. if (v.type === APP_CHAT_WITH_MULTIPLE_MODEL_RESTART)
  98. handleRestart()
  99. })
  100. const allToolIcons = useMemo(() => {
  101. const icons: Record<string, any> = {}
  102. modelConfig.agentConfig.tools?.forEach((item: any) => {
  103. icons[item.tool_name] = collectionList.find((collection: any) => collection.id === item.provider_id)?.icon
  104. })
  105. return icons
  106. }, [collectionList, modelConfig.agentConfig.tools])
  107. if (!chatList.length)
  108. return null
  109. return (
  110. <Chat
  111. config={config}
  112. chatList={chatList}
  113. isResponding={isResponding}
  114. noChatInput
  115. noStopResponding
  116. chatContainerClassName='p-4'
  117. chatFooterClassName='p-4 pb-0'
  118. suggestedQuestions={suggestedQuestions}
  119. onSend={doSend}
  120. showPromptLog
  121. questionIcon={<Avatar name={userProfile.name} size={40} />}
  122. allToolIcons={allToolIcons}
  123. hideLogModal
  124. noSpacing
  125. />
  126. )
  127. }
  128. export default memo(ChatItem)