|
@@ -16,6 +16,7 @@ import timezone from 'dayjs/plugin/timezone'
|
|
|
import { createContext, useContext } from 'use-context-selector'
|
|
|
import { useShallow } from 'zustand/react/shallow'
|
|
|
import { useTranslation } from 'react-i18next'
|
|
|
+import { UUID_NIL } from '../../base/chat/constants'
|
|
|
import s from './style.module.css'
|
|
|
import VarPanel from './var-panel'
|
|
|
import cn from '@/utils/classnames'
|
|
@@ -81,72 +82,92 @@ const PARAM_MAP = {
|
|
|
frequency_penalty: 'Frequency Penalty',
|
|
|
}
|
|
|
|
|
|
-// Format interface data for easy display
|
|
|
-const getFormattedChatList = (messages: ChatMessage[], conversationId: string, timezone: string, format: string) => {
|
|
|
- const newChatList: IChatItem[] = []
|
|
|
- messages.forEach((item: ChatMessage) => {
|
|
|
- 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') || [],
|
|
|
- })
|
|
|
- newChatList.push({
|
|
|
- id: item.id,
|
|
|
- content: item.answer,
|
|
|
- agent_thoughts: addFileInfos(item.agent_thoughts ? sortAgentSorts(item.agent_thoughts) : item.agent_thoughts, item.message_files),
|
|
|
- feedback: item.feedbacks.find(item => item.from_source === 'user'), // user feedback
|
|
|
- adminFeedback: item.feedbacks.find(item => item.from_source === 'admin'), // admin feedback
|
|
|
- feedbackDisabled: false,
|
|
|
- isAnswer: true,
|
|
|
- message_files: item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || [],
|
|
|
- log: [
|
|
|
- ...item.message,
|
|
|
- ...(item.message[item.message.length - 1]?.role !== 'assistant'
|
|
|
- ? [
|
|
|
- {
|
|
|
- role: 'assistant',
|
|
|
- text: item.answer,
|
|
|
- files: item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || [],
|
|
|
- },
|
|
|
- ]
|
|
|
- : []),
|
|
|
- ],
|
|
|
- workflow_run_id: item.workflow_run_id,
|
|
|
- conversationId,
|
|
|
- input: {
|
|
|
- inputs: item.inputs,
|
|
|
- query: item.query,
|
|
|
- },
|
|
|
- more: {
|
|
|
- time: dayjs.unix(item.created_at).tz(timezone).format(format),
|
|
|
- tokens: item.answer_tokens + item.message_tokens,
|
|
|
- latency: item.provider_response_latency.toFixed(2),
|
|
|
- },
|
|
|
- citation: item.metadata?.retriever_resources,
|
|
|
- annotation: (() => {
|
|
|
- if (item.annotation_hit_history) {
|
|
|
- return {
|
|
|
- id: item.annotation_hit_history.annotation_id,
|
|
|
- authorName: item.annotation_hit_history.annotation_create_account?.name || 'N/A',
|
|
|
- created_at: item.annotation_hit_history.created_at,
|
|
|
- }
|
|
|
+function appendQAToChatList(newChatList: IChatItem[], item: any, conversationId: string, timezone: string, format: string) {
|
|
|
+ newChatList.push({
|
|
|
+ id: item.id,
|
|
|
+ content: item.answer,
|
|
|
+ agent_thoughts: addFileInfos(item.agent_thoughts ? sortAgentSorts(item.agent_thoughts) : item.agent_thoughts, item.message_files),
|
|
|
+ feedback: item.feedbacks.find((item: any) => item.from_source === 'user'), // user feedback
|
|
|
+ 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') || [],
|
|
|
+ log: [
|
|
|
+ ...item.message,
|
|
|
+ ...(item.message[item.message.length - 1]?.role !== 'assistant'
|
|
|
+ ? [
|
|
|
+ {
|
|
|
+ role: 'assistant',
|
|
|
+ text: item.answer,
|
|
|
+ files: item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || [],
|
|
|
+ },
|
|
|
+ ]
|
|
|
+ : []),
|
|
|
+ ],
|
|
|
+ workflow_run_id: item.workflow_run_id,
|
|
|
+ conversationId,
|
|
|
+ input: {
|
|
|
+ inputs: item.inputs,
|
|
|
+ query: item.query,
|
|
|
+ },
|
|
|
+ more: {
|
|
|
+ time: dayjs.unix(item.created_at).tz(timezone).format(format),
|
|
|
+ tokens: item.answer_tokens + item.message_tokens,
|
|
|
+ latency: item.provider_response_latency.toFixed(2),
|
|
|
+ },
|
|
|
+ citation: item.metadata?.retriever_resources,
|
|
|
+ annotation: (() => {
|
|
|
+ if (item.annotation_hit_history) {
|
|
|
+ return {
|
|
|
+ id: item.annotation_hit_history.annotation_id,
|
|
|
+ authorName: item.annotation_hit_history.annotation_create_account?.name || 'N/A',
|
|
|
+ created_at: item.annotation_hit_history.created_at,
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- if (item.annotation) {
|
|
|
- return {
|
|
|
- id: item.annotation.id,
|
|
|
- authorName: item.annotation.account.name,
|
|
|
- logAnnotation: item.annotation,
|
|
|
- created_at: 0,
|
|
|
- }
|
|
|
+ if (item.annotation) {
|
|
|
+ return {
|
|
|
+ id: item.annotation.id,
|
|
|
+ authorName: item.annotation.account.name,
|
|
|
+ logAnnotation: item.annotation,
|
|
|
+ created_at: 0,
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- return undefined
|
|
|
- })(),
|
|
|
- })
|
|
|
+ return undefined
|
|
|
+ })(),
|
|
|
+ parentMessageId: `question-${item.id}`,
|
|
|
})
|
|
|
- return newChatList
|
|
|
+ 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') || [],
|
|
|
+ parentMessageId: item.parent_message_id || undefined,
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const getFormattedChatList = (messages: ChatMessage[], conversationId: string, timezone: string, format: string) => {
|
|
|
+ const newChatList: IChatItem[] = []
|
|
|
+ let nextMessageId = null
|
|
|
+ for (const item of messages) {
|
|
|
+ if (!item.parent_message_id) {
|
|
|
+ appendQAToChatList(newChatList, item, conversationId, timezone, format)
|
|
|
+ break
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!nextMessageId) {
|
|
|
+ appendQAToChatList(newChatList, item, conversationId, timezone, format)
|
|
|
+ nextMessageId = item.parent_message_id
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (item.id === nextMessageId || nextMessageId === UUID_NIL) {
|
|
|
+ appendQAToChatList(newChatList, item, conversationId, timezone, format)
|
|
|
+ nextMessageId = item.parent_message_id
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return newChatList.reverse()
|
|
|
}
|
|
|
|
|
|
// const displayedParams = CompletionParams.slice(0, -2)
|
|
@@ -171,6 +192,7 @@ function DetailPanel<T extends ChatConversationFullDetailResponse | CompletionCo
|
|
|
})))
|
|
|
const { t } = useTranslation()
|
|
|
const [items, setItems] = React.useState<IChatItem[]>([])
|
|
|
+ const fetchedMessages = useRef<ChatMessage[]>([])
|
|
|
const [hasMore, setHasMore] = useState(true)
|
|
|
const [varValues, setVarValues] = useState<Record<string, string>>({})
|
|
|
const fetchData = async () => {
|
|
@@ -192,7 +214,8 @@ function DetailPanel<T extends ChatConversationFullDetailResponse | CompletionCo
|
|
|
const varValues = messageRes.data[0].inputs
|
|
|
setVarValues(varValues)
|
|
|
}
|
|
|
- const newItems = [...getFormattedChatList(messageRes.data, detail.id, timezone!, t('appLog.dateTimeFormat') as string), ...items]
|
|
|
+ fetchedMessages.current = [...fetchedMessages.current, ...messageRes.data]
|
|
|
+ const newItems = getFormattedChatList(fetchedMessages.current, detail.id, timezone!, t('appLog.dateTimeFormat') as string)
|
|
|
if (messageRes.has_more === false && detail?.model_config?.configs?.introduction) {
|
|
|
newItems.unshift({
|
|
|
id: 'introduction',
|
|
@@ -435,7 +458,7 @@ function DetailPanel<T extends ChatConversationFullDetailResponse | CompletionCo
|
|
|
siteInfo={null}
|
|
|
/>
|
|
|
</div>
|
|
|
- : items.length < 8
|
|
|
+ : (items.length < 8 && !hasMore)
|
|
|
? <div className="pt-4 mb-4">
|
|
|
<Chat
|
|
|
config={{
|