mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 02:18:08 +08:00
fix: history messages toolcalls
This commit is contained in:
@ -42,7 +42,7 @@ import {
|
||||
import { TransferMethod } from '@/types/app'
|
||||
import { addFileInfos, sortAgentSorts } from '../../../tools/utils'
|
||||
import { CONVERSATION_ID_INFO } from '../constants'
|
||||
import { buildChatItemTree, getProcessedSystemVariablesFromUrlParams, getRawInputsFromUrlParams, getRawUserVariablesFromUrlParams } from '../utils'
|
||||
import { buildChatItemTree, buildToolCallsFromHistorySequence, getProcessedSystemVariablesFromUrlParams, getRawInputsFromUrlParams, getRawUserVariablesFromUrlParams } from '../utils'
|
||||
|
||||
function getFormattedChatList(messages: any[]) {
|
||||
const newChatList: ChatItem[] = []
|
||||
@ -58,7 +58,8 @@ function getFormattedChatList(messages: any[]) {
|
||||
const answerFiles = item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || []
|
||||
newChatList.push({
|
||||
id: item.id,
|
||||
content: item.answer,
|
||||
content: buildToolCallsFromHistorySequence(item).message,
|
||||
toolCalls: buildToolCallsFromHistorySequence(item).toolCalls,
|
||||
agent_thoughts: addFileInfos(item.agent_thoughts ? sortAgentSorts(item.agent_thoughts) : item.agent_thoughts, item.message_files),
|
||||
feedback: item.feedback,
|
||||
isAnswer: true,
|
||||
|
||||
@ -2,7 +2,7 @@ import type { FileEntity } from '@/app/components/base/file-uploader/types'
|
||||
import type { TypeWithI18N } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import type { InputVarType } from '@/app/components/workflow/types'
|
||||
import type { Annotation, MessageRating } from '@/models/log'
|
||||
import type { FileResponse, ToolCallItem } from '@/types/workflow'
|
||||
import type { FileResponse, IconObject, ToolCallItem } from '@/types/workflow'
|
||||
|
||||
export type MessageMore = {
|
||||
time: string
|
||||
@ -148,3 +148,39 @@ export type InputForm = {
|
||||
hide: boolean
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export type ToolCallDetail = {
|
||||
id: string
|
||||
name: string
|
||||
arguments: string
|
||||
result: string
|
||||
elapsed_time?: number
|
||||
icon?: string | IconObject
|
||||
icon_dark?: string | IconObject
|
||||
}
|
||||
export type SequenceSegment = | { type: 'content', start: number, end: number }
|
||||
| { type: 'reasoning', index: number }
|
||||
| { type: 'tool_call', index: number }
|
||||
|
||||
export type GenerationDetail = {
|
||||
reasoning_content?: string[]
|
||||
tool_calls?: ToolCallDetail[]
|
||||
sequence?: SequenceSegment[]
|
||||
}
|
||||
|
||||
export type ChatMessageRes = {
|
||||
id: string
|
||||
parent_message_id?: string | null
|
||||
workflow_run_id?: string
|
||||
answer?: string
|
||||
query: string
|
||||
message_files: {
|
||||
id: string
|
||||
type: string
|
||||
url: string
|
||||
belongs_to: string
|
||||
}[]
|
||||
feedback?: FeedbackType
|
||||
metadata?: Metadata
|
||||
generation_detail?: GenerationDetail
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import type { IChatItem } from './chat/type'
|
||||
import type { ChatMessageRes, IChatItem } from './chat/type'
|
||||
import type { ChatItem, ChatItemInTree } from './types'
|
||||
import type { ToolCallItem } from '@/types/workflow'
|
||||
import { v4 as uuidV4 } from 'uuid'
|
||||
import { UUID_NIL } from './constants'
|
||||
|
||||
async function decodeBase64AndDecompress(base64String: string) {
|
||||
@ -232,8 +234,66 @@ function getThreadMessages(tree: ChatItemInTree[], targetMessageId?: string): Ch
|
||||
return ret
|
||||
}
|
||||
|
||||
const buildToolCallsFromHistorySequence = (message: ChatMessageRes): {
|
||||
toolCalls: ToolCallItem[]
|
||||
message: string
|
||||
} => {
|
||||
const { answer, generation_detail } = message
|
||||
|
||||
if (!generation_detail) {
|
||||
return { toolCalls: [], message: answer || '' }
|
||||
}
|
||||
|
||||
const { reasoning_content = [], tool_calls = [], sequence = [] } = generation_detail
|
||||
const toolCalls: ToolCallItem[] = []
|
||||
let answerMessage = ''
|
||||
|
||||
sequence.forEach((segment) => {
|
||||
switch (segment.type) {
|
||||
case 'content': {
|
||||
const text = answer?.substring(segment.start, segment.end)
|
||||
if (text?.trim()) {
|
||||
answerMessage += text
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'reasoning': {
|
||||
const reasoning = reasoning_content[segment.index]
|
||||
if (reasoning) {
|
||||
toolCalls.push({
|
||||
id: uuidV4(),
|
||||
type: 'thought',
|
||||
thoughtOutput: reasoning,
|
||||
thoughtCompleted: true,
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'tool_call': {
|
||||
const toolCall = tool_calls[segment.index]
|
||||
if (toolCall) {
|
||||
toolCalls.push({
|
||||
id: uuidV4(),
|
||||
type: 'tool',
|
||||
toolName: toolCall.name,
|
||||
toolArguments: toolCall.arguments,
|
||||
toolOutput: toolCall.result,
|
||||
toolDuration: toolCall.elapsed_time,
|
||||
toolIcon: toolCall.icon,
|
||||
toolIconDark: toolCall.icon_dark,
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return { toolCalls, message: answerMessage || '' }
|
||||
}
|
||||
|
||||
export {
|
||||
buildChatItemTree,
|
||||
buildToolCallsFromHistorySequence,
|
||||
getLastAnswer,
|
||||
getProcessedInputsFromUrlParams,
|
||||
getProcessedSystemVariablesFromUrlParams,
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
import type { IChatItem } from '@/app/components/base/chat/chat/type'
|
||||
import type {
|
||||
ChatMessageRes,
|
||||
IChatItem,
|
||||
} from '@/app/components/base/chat/chat/type'
|
||||
import type { ChatItem, ChatItemInTree } from '@/app/components/base/chat/types'
|
||||
import { RiCloseLine } from '@remixicon/react'
|
||||
import {
|
||||
@ -9,7 +12,7 @@ import {
|
||||
} from 'react'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import Chat from '@/app/components/base/chat/chat'
|
||||
import { buildChatItemTree, getThreadMessages } from '@/app/components/base/chat/utils'
|
||||
import { buildChatItemTree, buildToolCallsFromHistorySequence, getThreadMessages } from '@/app/components/base/chat/utils'
|
||||
import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { fetchConversationMessages } from '@/service/debug'
|
||||
@ -21,10 +24,10 @@ import {
|
||||
import { formatWorkflowRunIdentifier } from '../../utils'
|
||||
import UserInput from './user-input'
|
||||
|
||||
function getFormattedChatList(messages: any[]) {
|
||||
function getFormattedChatList(messages: ChatMessageRes[]) {
|
||||
const res: ChatItem[] = []
|
||||
messages.forEach((item: any) => {
|
||||
const questionFiles = item.message_files?.filter((file: any) => file.belongs_to === 'user') || []
|
||||
messages.forEach((item: ChatMessageRes) => {
|
||||
const questionFiles = item.message_files?.filter(file => file.belongs_to === 'user') || []
|
||||
res.push({
|
||||
id: `question-${item.id}`,
|
||||
content: item.query,
|
||||
@ -35,7 +38,8 @@ function getFormattedChatList(messages: any[]) {
|
||||
const answerFiles = item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || []
|
||||
res.push({
|
||||
id: item.id,
|
||||
content: item.answer,
|
||||
content: buildToolCallsFromHistorySequence(item).message,
|
||||
toolCalls: buildToolCallsFromHistorySequence(item).toolCalls,
|
||||
feedback: item.feedback,
|
||||
isAnswer: true,
|
||||
citation: item.metadata?.retriever_resources,
|
||||
@ -63,7 +67,7 @@ const ChatRecord = () => {
|
||||
setFetched(false)
|
||||
const res = await fetchConversationMessages(appDetail.id, currentConversationID)
|
||||
|
||||
const newAllChatItems = getFormattedChatList((res as any).data)
|
||||
const newAllChatItems = getFormattedChatList((res as any).data as ChatMessageRes[])
|
||||
|
||||
const tree = buildChatItemTree(newAllChatItems)
|
||||
setChatItemTree(tree)
|
||||
|
||||
Reference in New Issue
Block a user