file in chat question

This commit is contained in:
StyleZhang 2024-09-19 16:54:34 +08:00
parent 396a240e68
commit 2b0c39ed3f
10 changed files with 90 additions and 43 deletions

View File

@ -71,12 +71,7 @@ const ChatInputArea = ({
notify({ type: 'info', message: t('appAnnotation.errorMessage.queryRequired') })
return
}
onSend(query, files.filter(file => file.progress !== -1).map(fileItem => ({
type: fileItem.fileType,
transfer_method: fileItem.type,
url: fileItem.url || '',
upload_file_id: fileItem.fileStorageId || '',
})))
onSend(query, files)
setQuery('')
setFiles([])
}

View File

@ -13,7 +13,6 @@ import type {
ChatItem,
Inputs,
PromptVariable,
VisionFile,
} from '../types'
import { TransferMethod } from '@/types/app'
import { useToastContext } from '@/app/components/base/toast'
@ -23,6 +22,8 @@ import type { Annotation } from '@/models/log'
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
import useTimestamp from '@/hooks/use-timestamp'
import { AudioPlayerManager } from '@/app/components/base/audio-btn/audio.player.manager'
import type { FileEntity } from '@/app/components/base/file-uploader/types'
import { getProcessedFiles } from '@/app/components/base/file-uploader/utils'
type GetAbortController = (abortController: AbortController) => void
type SendCallback = {
@ -196,7 +197,11 @@ export const useChat = (
const handleSend = useCallback(async (
url: string,
data: any,
data: {
query: string
files?: FileEntity[]
[key: string]: any
},
{
onGetConversationMessages,
onGetSuggestedQuestions,
@ -244,13 +249,16 @@ export const useChat = (
handleResponding(true)
hasStopResponded.current = false
const { query, files, ...restData } = data
const bodyParams = {
response_mode: 'streaming',
conversation_id: conversationId.current,
...data,
files: getProcessedFiles(files || []),
query,
...restData,
}
if (bodyParams?.files?.length) {
bodyParams.files = bodyParams.files.map((item: VisionFile) => {
bodyParams.files = bodyParams.files.map((item) => {
if (item.transfer_method === TransferMethod.local_file) {
return {
...item,

View File

@ -10,7 +10,7 @@ import type { Theme } from '../embedded-chatbot/theme/theme-context'
import { CssTransform } from '../embedded-chatbot/theme/utils'
import { User } from '@/app/components/base/icons/src/public/avatar'
import { Markdown } from '@/app/components/base/markdown'
import ImageGallery from '@/app/components/base/image-gallery'
import { FileList } from '@/app/components/base/file-uploader'
type QuestionProps = {
item: ChatItem
@ -27,7 +27,6 @@ const Question: FC<QuestionProps> = ({
message_files,
} = item
const imgSrcs = message_files?.length ? message_files.map(item => item.url) : []
return (
<div className='flex justify-end mb-2 last:mb-0 pl-10'>
<div className='group relative mr-4'>
@ -36,8 +35,12 @@ const Question: FC<QuestionProps> = ({
style={theme?.chatBubbleColorStyle ? CssTransform(theme.chatBubbleColorStyle) : {}}
>
{
!!imgSrcs.length && (
<ImageGallery srcs={imgSrcs} />
!!message_files?.length && (
<FileList
files={message_files}
showDeleteAction={false}
showDownloadAction={false}
/>
)
}
<Markdown content={content} />

View File

@ -1,6 +1,7 @@
import type { TypeWithI18N } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { Annotation, MessageRating } from '@/models/log'
import type { VisionFile } from '@/types/app'
import type { FileEntity } from '@/app/components/base/file-uploader/types'
export type MessageMore = {
time: string
@ -90,7 +91,7 @@ export type IChatItem = {
suggestedQuestions?: string[]
log?: { role: string; text: string; files?: VisionFile[] }[]
agent_thoughts?: ThoughtItem[]
message_files?: VisionFile[]
message_files?: FileEntity[]
workflow_run_id?: string
// for agent log
conversationId?: string

View File

@ -1,11 +1,11 @@
import type {
ModelConfig,
VisionFile,
VisionSettings,
} from '@/types/app'
import type { IChatItem } from '@/app/components/base/chat/chat/type'
import type { NodeTracing } from '@/types/workflow'
import type { WorkflowRunningStatus } from '@/app/components/workflow/types'
import type { FileEntity } from '@/app/components/base/file-uploader/types'
export type { VisionFile } from '@/types/app'
export { TransferMethod } from '@/types/app'
@ -63,7 +63,7 @@ export type ChatItem = IChatItem & {
conversationId?: string
}
export type OnSend = (message: string, files?: VisionFile[]) => void
export type OnSend = (message: string, files?: FileEntity[]) => void
export type Callback = {
onSuccess: () => void

View File

@ -1,22 +1,25 @@
import { isImage } from '../utils'
import { useFile } from '../hooks'
import { useStore } from '../store'
import type { FileEntity } from '../types'
import FileImageItem from './file-image-item'
import FileItem from './file-item'
import type { FileUpload } from '@/app/components/base/features/types'
type FileListProps = {
fileConfig: FileUpload
files: FileEntity[]
onRemove?: (fileId: string) => void
onReUpload?: (fileId: string) => void
showDeleteAction?: boolean
showDownloadAction?: boolean
}
const FileList = ({
fileConfig,
export const FileList = ({
files,
onReUpload,
onRemove,
showDeleteAction = true,
showDownloadAction = false,
}: FileListProps) => {
const files = useStore(s => s.files)
const {
handleRemoveFile,
handleReUploadFile,
} = useFile(fileConfig)
return (
<div className='flex flex-wrap gap-2'>
{
@ -28,9 +31,9 @@ const FileList = ({
fileId={file.fileId}
imageUrl={file.base64Url}
progress={file.progress}
showDeleteAction
onRemove={handleRemoveFile}
onReUpload={handleReUploadFile}
showDeleteAction={showDeleteAction}
onRemove={onRemove}
onReUpload={onReUpload}
/>
)
}
@ -41,10 +44,10 @@ const FileList = ({
fileId={file.fileId}
file={file.file}
progress={file.progress}
showDeleteAction
showDownloadAction={false}
onRemove={handleRemoveFile}
onReUpload={handleReUploadFile}
showDeleteAction={showDeleteAction}
showDownloadAction={showDownloadAction}
onRemove={onRemove}
onReUpload={onReUpload}
/>
)
})
@ -53,4 +56,23 @@ const FileList = ({
)
}
export default FileList
type FileListInChatInputProps = {
fileConfig: FileUpload
}
export const FileListInChatInput = ({
fileConfig,
}: FileListInChatInputProps) => {
const files = useStore(s => s.files)
const {
handleRemoveFile,
handleReUploadFile,
} = useFile(fileConfig)
return (
<FileList
files={files}
onReUpload={handleReUploadFile}
onRemove={handleRemoveFile}
/>
)
}

View File

@ -2,5 +2,6 @@ export { default as FileUploaderInAttachmentWrapper } from './file-uploader-in-a
export { default as FileItemInAttachment } from './file-uploader-in-attachment/file-item'
export { default as FileUploaderInChatInput } from './file-uploader-in-chat-input'
export { default as FileTypeIcon } from './file-type-icon'
export { default as FileListInChatInput } from './file-uploader-in-chat-input/file-list'
export { default as FileItemInChatInput } from './file-uploader-in-chat-input/file-list'
export { FileListInChatInput } from './file-uploader-in-chat-input/file-list'
export { FileList } from './file-uploader-in-chat-input/file-list'
export { default as FileItem } from './file-uploader-in-chat-input/file-item'

View File

@ -1,4 +1,5 @@
import { FileAppearanceTypeEnum } from './types'
import type { FileEntity } from './types'
import { upload } from '@/service/base'
import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
@ -83,3 +84,12 @@ export const getFileType = (file?: File) => {
return ''
}
export const getProcessedFiles = (files: FileEntity[]) => {
return files.filter(file => file.progress !== -1).map(fileItem => ({
type: fileItem.fileType,
transfer_method: fileItem.type,
url: fileItem.url || '',
upload_file_id: fileItem.fileStorageId || '',
}))
}

View File

@ -407,9 +407,9 @@ const WorkflowWrap = memo(() => {
const initialFeatures: FeaturesData = {
file: {
image: {
enabled: !!features.file_upload?.image.enabled,
number_limits: features.file_upload?.image.number_limits || 3,
transfer_methods: features.file_upload?.image.transfer_methods || ['local_file', 'remote_url'],
enabled: !!features.file_upload?.image?.enabled,
number_limits: features.file_upload?.image?.number_limits || 3,
transfer_methods: features.file_upload?.image?.transfer_methods || ['local_file', 'remote_url'],
},
enabled: !!(features.file_upload?.enabled || features.file_upload?.image?.enabled),
allowed_file_types: features.file_upload?.allowed_file_types || [SupportUploadFileTypes.image],

View File

@ -15,8 +15,9 @@ import type {
} from '@/app/components/base/chat/types'
import { useToastContext } from '@/app/components/base/toast'
import { TransferMethod } from '@/types/app'
import type { VisionFile } from '@/types/app'
import { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel/utils'
import { getProcessedFiles } from '@/app/components/base/file-uploader/utils'
import type { FileEntity } from '@/app/components/base/file-uploader/types'
type GetAbortController = (abortController: AbortController) => void
type SendCallback = {
@ -143,7 +144,11 @@ export const useChat = (
}, [handleUpdateChatList])
const handleSend = useCallback((
params: any,
params: {
query: string
files?: FileEntity[]
[key: string]: any
},
{
onGetSuggestedQuestions,
}: SendCallback,
@ -182,12 +187,14 @@ export const useChat = (
handleResponding(true)
const { files, ...restParams } = params
const bodyParams = {
conversation_id: conversationId.current,
...params,
files: getProcessedFiles(files || []),
...restParams,
}
if (bodyParams?.files?.length) {
bodyParams.files = bodyParams.files.map((item: VisionFile) => {
bodyParams.files = bodyParams.files.map((item) => {
if (item.transfer_method === TransferMethod.local_file) {
return {
...item,