diff --git a/web/app/components/app/log/list.tsx b/web/app/components/app/log/list.tsx index 50bfe09bdc..cfc5452c08 100644 --- a/web/app/components/app/log/list.tsx +++ b/web/app/components/app/log/list.tsx @@ -41,6 +41,7 @@ import { useAppContext } from '@/context/app-context' import useTimestamp from '@/hooks/use-timestamp' import Tooltip from '@/app/components/base/tooltip' import { CopyIcon } from '@/app/components/base/copy-icon' +import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils' dayjs.extend(utc) dayjs.extend(timezone) @@ -82,6 +83,7 @@ const PARAM_MAP = { } function appendQAToChatList(newChatList: IChatItem[], item: any, conversationId: string, timezone: string, format: string) { + const answerFiles = item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || [] newChatList.push({ id: item.id, content: item.answer, @@ -90,7 +92,7 @@ function appendQAToChatList(newChatList: IChatItem[], item: any, conversationId: adminFeedback: item.feedbacks.find((item: any) => item.from_source === 'admin'), // admin feedback feedbackDisabled: false, isAnswer: true, - message_files: item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || [], + message_files: getProcessedFilesFromResponse(answerFiles.map((item: any) => ({ ...item, related_id: item.id }))), log: [ ...item.message, ...(item.message[item.message.length - 1]?.role !== 'assistant' @@ -137,11 +139,12 @@ function appendQAToChatList(newChatList: IChatItem[], item: any, conversationId: })(), parentMessageId: `question-${item.id}`, }) + const questionFiles = item.message_files?.filter((file: any) => file.belongs_to === 'user') || [] newChatList.push({ id: `question-${item.id}`, content: item.inputs.query || item.inputs.default_input || item.query, // text generation: item.inputs.query; chat: item.query isAnswer: false, - message_files: item.message_files?.filter((file: any) => file.belongs_to === 'user') || [], + message_files: getProcessedFilesFromResponse(questionFiles.map((item: any) => ({ ...item, related_id: item.id }))), parentMessageId: item.parent_message_id || undefined, }) } diff --git a/web/app/components/base/chat/chat/answer/agent-content.tsx b/web/app/components/base/chat/chat/answer/agent-content.tsx index b52dd54607..6f03c938f1 100644 --- a/web/app/components/base/chat/chat/answer/agent-content.tsx +++ b/web/app/components/base/chat/chat/answer/agent-content.tsx @@ -2,11 +2,11 @@ import type { FC } from 'react' import { memo } from 'react' import type { ChatItem, - VisionFile, } from '../../types' import { Markdown } from '@/app/components/base/markdown' import Thought from '@/app/components/base/chat/chat/thought' -import ImageGallery from '@/app/components/base/image-gallery' +import { FileList } from '@/app/components/base/file-uploader' +import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils' type AgentContentProps = { item: ChatItem @@ -21,12 +21,6 @@ const AgentContent: FC = ({ agent_thoughts, } = item - const getImgs = (list?: VisionFile[]) => { - if (!list) - return [] - return list.filter(file => file.type === 'image' && file.belongs_to === 'assistant') - } - if (annotation?.logAnnotation) return @@ -46,9 +40,16 @@ const AgentContent: FC = ({ /> )} - {getImgs(thought.message_files).length > 0 && ( - file.url)} /> - )} + { + !!thought.message_files?.length && ( + ({ ...item, related_id: item.id })))} + showDeleteAction={false} + showDownloadAction={true} + canPreview={true} + /> + ) + } ))} diff --git a/web/app/components/base/chat/chat/answer/index.tsx b/web/app/components/base/chat/chat/answer/index.tsx index d199530815..16ad8f84c3 100644 --- a/web/app/components/base/chat/chat/answer/index.tsx +++ b/web/app/components/base/chat/chat/answer/index.tsx @@ -58,6 +58,7 @@ const Answer: FC = ({ annotation, workflowProcess, allFiles, + message_files, } = item const hasAgentThoughts = !!agent_thoughts?.length @@ -179,6 +180,17 @@ const Answer: FC = ({ /> ) } + { + !!message_files?.length && ( + + ) + } { annotation?.id && annotation.authorName && ( = ({ ) } diff --git a/web/app/components/base/chat/chat/type.ts b/web/app/components/base/chat/chat/type.ts index 365c38c790..40cc32e859 100644 --- a/web/app/components/base/chat/chat/type.ts +++ b/web/app/components/base/chat/chat/type.ts @@ -1,6 +1,5 @@ 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' import type { InputVarType } from '@/app/components/workflow/types' import type { FileResponse } from '@/types/workflow' @@ -45,7 +44,7 @@ export type ThoughtItem = { observation: string position: number files?: string[] - message_files?: VisionFile[] + message_files?: FileEntity[] } export type CitationItem = { @@ -91,7 +90,7 @@ export type IChatItem = { useCurrentUserAvatar?: boolean isOpeningStatement?: boolean suggestedQuestions?: string[] - log?: { role: string; text: string; files?: VisionFile[] }[] + log?: { role: string; text: string; files?: FileEntity[] }[] agent_thoughts?: ThoughtItem[] message_files?: FileEntity[] workflow_run_id?: string diff --git a/web/app/components/base/chat/utils.ts b/web/app/components/base/chat/utils.ts index 305df5995d..3840f6a2b8 100644 --- a/web/app/components/base/chat/utils.ts +++ b/web/app/components/base/chat/utils.ts @@ -1,6 +1,7 @@ import { addFileInfos, sortAgentSorts } from '../../tools/utils' import { UUID_NIL } from './constants' import type { ChatItem } from './types' +import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils' async function decodeBase64AndDecompress(base64String: string) { const binaryString = atob(base64String) @@ -30,6 +31,7 @@ function getLastAnswer(chatList: ChatItem[]) { function appendQAToChatList(chatList: ChatItem[], item: any) { // we append answer first and then question since will reverse the whole chatList later + const answerFiles = item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || [] chatList.push({ id: item.id, content: item.answer, @@ -37,13 +39,14 @@ function appendQAToChatList(chatList: ChatItem[], item: any) { feedback: item.feedback, isAnswer: true, citation: item.retriever_resources, - message_files: item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || [], + message_files: getProcessedFilesFromResponse(answerFiles.map((item: any) => ({ ...item, related_id: item.id }))), }) + const questionFiles = item.message_files?.filter((file: any) => file.belongs_to === 'user') || [] chatList.push({ id: `question-${item.id}`, content: item.query, isAnswer: false, - message_files: item.message_files?.filter((file: any) => file.belongs_to === 'user') || [], + message_files: getProcessedFilesFromResponse(questionFiles.map((item: any) => ({ ...item, related_id: item.id }))), }) } diff --git a/web/app/components/base/file-uploader/file-input.tsx b/web/app/components/base/file-uploader/file-input.tsx index e981278c14..ff71cf1030 100644 --- a/web/app/components/base/file-uploader/file-input.tsx +++ b/web/app/components/base/file-uploader/file-input.tsx @@ -21,7 +21,7 @@ const FileInput = ({ const allowedFileTypes = fileConfig.allowed_file_types const isCustom = allowedFileTypes?.includes(SupportUploadFileTypes.custom) - const exts = isCustom ? (fileConfig.allowed_file_extensions || []) : (allowedFileTypes?.map(type => FILE_EXTS[type]) || []).flat().map(item => `.${item}`) + const exts = isCustom ? (fileConfig.allowed_file_extensions?.map(item => `.${item}`) || []) : (allowedFileTypes?.map(type => FILE_EXTS[type]) || []).flat().map(item => `.${item}`) const accept = exts.join(',') return ( diff --git a/web/app/components/base/file-uploader/utils.ts b/web/app/components/base/file-uploader/utils.ts index ae4b333003..4c7ef0d89b 100644 --- a/web/app/components/base/file-uploader/utils.ts +++ b/web/app/components/base/file-uploader/utils.ts @@ -142,7 +142,7 @@ export const getFileNameFromUrl = (url: string) => { export const getSupportFileExtensionList = (allowFileTypes: string[], allowFileExtensions: string[]) => { if (allowFileTypes.includes(SupportUploadFileTypes.custom)) - return allowFileExtensions + return allowFileExtensions.map(item => item.toUpperCase()) return allowFileTypes.map(type => FILE_EXTS[type]).flat() } diff --git a/web/app/components/tools/utils/index.ts b/web/app/components/tools/utils/index.ts index 0c462aa6fc..988c2c725c 100644 --- a/web/app/components/tools/utils/index.ts +++ b/web/app/components/tools/utils/index.ts @@ -1,5 +1,5 @@ import type { ThoughtItem } from '@/app/components/base/chat/chat/type' -import type { VisionFile } from '@/types/app' +import type { FileEntity } from '@/app/components/base/file-uploader/types' export const sortAgentSorts = (list: ThoughtItem[]) => { if (!list) @@ -11,14 +11,14 @@ export const sortAgentSorts = (list: ThoughtItem[]) => { return temp } -export const addFileInfos = (list: ThoughtItem[], messageFiles: VisionFile[]) => { +export const addFileInfos = (list: ThoughtItem[], messageFiles: FileEntity[]) => { if (!list || !messageFiles) return list return list.map((item) => { if (item.files && item.files?.length > 0) { return { ...item, - message_files: item.files.map(fileId => messageFiles.find(file => file.id === fileId)) as VisionFile[], + message_files: item.files.map(fileId => messageFiles.find(file => file.id === fileId)) as FileEntity[], } } return item diff --git a/web/app/components/workflow/panel/chat-record/index.tsx b/web/app/components/workflow/panel/chat-record/index.tsx index 16d2c304a7..2786310288 100644 --- a/web/app/components/workflow/panel/chat-record/index.tsx +++ b/web/app/components/workflow/panel/chat-record/index.tsx @@ -17,22 +17,25 @@ import { fetchConversationMessages } from '@/service/debug' import { useStore as useAppStore } from '@/app/components/app/store' import Loading from '@/app/components/base/loading' import { UUID_NIL } from '@/app/components/base/chat/constants' +import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils' function appendQAToChatList(newChatList: ChatItem[], item: any) { + const answerFiles = item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || [] newChatList.push({ id: item.id, content: item.answer, feedback: item.feedback, isAnswer: true, citation: item.metadata?.retriever_resources, - message_files: item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || [], + message_files: getProcessedFilesFromResponse(answerFiles.map((item: any) => ({ ...item, related_id: item.id }))), workflow_run_id: item.workflow_run_id, }) + const questionFiles = item.message_files?.filter((file: any) => file.belongs_to === 'user') || [] newChatList.push({ id: `question-${item.id}`, content: item.query, isAnswer: false, - message_files: item.message_files?.filter((file: any) => file.belongs_to === 'user') || [], + message_files: getProcessedFilesFromResponse(questionFiles.map((item: any) => ({ ...item, related_id: item.id }))), }) }