chat-wrapper.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import {
  2. forwardRef,
  3. memo,
  4. useCallback,
  5. useImperativeHandle,
  6. useMemo,
  7. } from 'react'
  8. import { useNodes } from 'reactflow'
  9. import { BlockEnum } from '../../types'
  10. import {
  11. useStore,
  12. useWorkflowStore,
  13. } from '../../store'
  14. import type { StartNodeType } from '../../nodes/start/types'
  15. import Empty from './empty'
  16. import UserInput from './user-input'
  17. import { useChat } from './hooks'
  18. import type { ChatWrapperRefType } from './index'
  19. import Chat from '@/app/components/base/chat/chat'
  20. import type { OnSend } from '@/app/components/base/chat/types'
  21. import { useFeaturesStore } from '@/app/components/base/features/hooks'
  22. import {
  23. fetchSuggestedQuestions,
  24. stopChatMessageResponding,
  25. } from '@/service/debug'
  26. import { useStore as useAppStore } from '@/app/components/app/store'
  27. const ChatWrapper = forwardRef<ChatWrapperRefType>((_, ref) => {
  28. const nodes = useNodes<StartNodeType>()
  29. const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
  30. const startVariables = startNode?.data.variables
  31. const appDetail = useAppStore(s => s.appDetail)
  32. const workflowStore = useWorkflowStore()
  33. const featuresStore = useFeaturesStore()
  34. const inputs = useStore(s => s.inputs)
  35. const features = featuresStore!.getState().features
  36. const config = useMemo(() => {
  37. return {
  38. opening_statement: features.opening?.opening_statement || '',
  39. suggested_questions: features.opening?.suggested_questions || [],
  40. suggested_questions_after_answer: features.suggested,
  41. text_to_speech: features.text2speech,
  42. speech_to_text: features.speech2text,
  43. retriever_resource: features.citation,
  44. sensitive_word_avoidance: features.moderation,
  45. file_upload: features.file,
  46. }
  47. }, [features])
  48. const {
  49. conversationId,
  50. chatList,
  51. handleStop,
  52. isResponding,
  53. suggestedQuestions,
  54. handleSend,
  55. handleRestart,
  56. } = useChat(
  57. config,
  58. {
  59. inputs,
  60. promptVariables: (startVariables as any) || [],
  61. },
  62. [],
  63. taskId => stopChatMessageResponding(appDetail!.id, taskId),
  64. )
  65. const doSend = useCallback<OnSend>((query, files) => {
  66. handleSend(
  67. {
  68. query,
  69. files,
  70. inputs: workflowStore.getState().inputs,
  71. conversation_id: conversationId,
  72. },
  73. {
  74. onGetSuggestedQuestions: (messageId, getAbortController) => fetchSuggestedQuestions(appDetail!.id, messageId, getAbortController),
  75. },
  76. )
  77. }, [conversationId, handleSend, workflowStore, appDetail])
  78. useImperativeHandle(ref, () => {
  79. return {
  80. handleRestart,
  81. }
  82. }, [handleRestart])
  83. return (
  84. <Chat
  85. config={{
  86. ...config,
  87. supportCitationHitInfo: true,
  88. } as any}
  89. chatList={chatList}
  90. isResponding={isResponding}
  91. chatContainerClassName='px-4'
  92. chatContainerInnerClassName='pt-6'
  93. chatFooterClassName='px-4 rounded-bl-2xl'
  94. chatFooterInnerClassName='pb-4'
  95. onSend={doSend}
  96. onStopResponding={handleStop}
  97. chatNode={(
  98. <>
  99. <UserInput />
  100. {
  101. !chatList.length && (
  102. <Empty />
  103. )
  104. }
  105. </>
  106. )}
  107. suggestedQuestions={suggestedQuestions}
  108. showPromptLog
  109. chatAnswerContainerInner='!pr-2'
  110. />
  111. )
  112. })
  113. ChatWrapper.displayName = 'ChatWrapper'
  114. export default memo(ChatWrapper)