From 093084ef7f55fffb0aafa89c929de3ece08b5fcd Mon Sep 17 00:00:00 2001 From: Wenjie Zhang Date: Mon, 27 Oct 2025 18:41:35 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=96=B0=E6=97=A7=E6=A0=BC=E5=BC=8F=E5=85=BC?= =?UTF-8?q?=E5=AE=B9=E5=B9=B6=E4=BC=98=E5=8C=96=E5=B7=A5=E5=85=B7=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E5=8F=82=E6=95=B0=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/advanced/document-processing.md | 1 + web/src/components/AgentChatComponent.vue | 1 + web/src/components/AgentMessageComponent.vue | 52 +++++++-- web/src/utils/messageProcessor.js | 106 ++++++++++++++++++- 4 files changed, 151 insertions(+), 9 deletions(-) diff --git a/docs/advanced/document-processing.md b/docs/advanced/document-processing.md index 3bbb9890..1e4a2d99 100644 --- a/docs/advanced/document-processing.md +++ b/docs/advanced/document-processing.md @@ -131,6 +131,7 @@ uv run scripts/batch_upload.py \ --wait-for-completion \ --poll-interval 5 \ --recursive \ + --enable-ocr mineru_ocr \ # mineru_official, paddlex_ocr, onnx_rapid_ocr --record-file scripts/tmp/batch_processed_files_1029.txt ``` diff --git a/web/src/components/AgentChatComponent.vue b/web/src/components/AgentChatComponent.vue index df714f76..a8209206 100644 --- a/web/src/components/AgentChatComponent.vue +++ b/web/src/components/AgentChatComponent.vue @@ -388,6 +388,7 @@ const resetOnGoingConv = (threadId = null, preserveMessages = false) => { const _processStreamChunk = (chunk, threadId) => { const { status, msg, request_id, message } = chunk; const threadState = getThreadState(threadId); + // console.log('msg:', msg); if (!threadState) return false; diff --git a/web/src/components/AgentMessageComponent.vue b/web/src/components/AgentMessageComponent.vue index cf0913a9..45ec6009 100644 --- a/web/src/components/AgentMessageComponent.vue +++ b/web/src/components/AgentMessageComponent.vue @@ -33,8 +33,8 @@ 生成过程中出现异常 -
-
+
+
@@ -47,15 +47,17 @@
-
+
- 参数: {{ toolCall.args || toolCall.function.arguments }} + 参数: + {{ getFormattedToolArgs(toolCall) }} + {{ toolCall.args || toolCall.function?.arguments }}
@@ -146,13 +148,51 @@ const { availableTools } = storeToRefs(agentStore); // 工具相关方法 const getToolNameByToolCall = (toolCall) => { - const toolId = toolCall.name || toolCall.function.name; + const toolId = toolCall.name || toolCall.function?.name; const toolsList = availableTools.value ? Object.values(availableTools.value) : []; const tool = toolsList.find(t => t.id === toolId); return tool ? tool.name : toolId; }; +const getFormattedToolArgs = (toolCall) => { + const args = toolCall.args || toolCall.function?.arguments; + if (!args) return ''; + + try { + // 尝试解析JSON格式的参数 + if (typeof args === 'string' && args.trim().startsWith('{')) { + const parsed = JSON.parse(args); + return JSON.stringify(parsed, null, 2); + } + } catch (e) { + // 如果解析失败,直接返回原始字符串 + } + + return args; +}; + +// 过滤有效的工具调用 +const validToolCalls = computed(() => { + if (!props.message.tool_calls || !Array.isArray(props.message.tool_calls)) { + return []; + } + + return props.message.tool_calls.filter(toolCall => { + // 过滤掉无效的工具调用 + return toolCall && + (toolCall.id || toolCall.name) && + (toolCall.args !== undefined || + toolCall.function?.arguments !== undefined || + toolCall.tool_call_result !== undefined); + }); +}); + const parsedData = computed(() => { + // 调试工具调用处理 + if (validToolCalls.value && validToolCalls.value.length > 0) { + console.log('Valid tool calls in message:', validToolCalls.value); + } + // Start with default values from the prop to avoid mutation. let content = props.message.content.trim() || ''; let reasoning_content = props.message.additional_kwargs?.reasoning_content || ''; diff --git a/web/src/utils/messageProcessor.js b/web/src/utils/messageProcessor.js index a892c42e..0fc75fa3 100644 --- a/web/src/utils/messageProcessor.js +++ b/web/src/utils/messageProcessor.js @@ -12,8 +12,12 @@ export class MessageProcessor { // 构建工具响应映射 for (const item of msgs) { - if (item.type === 'tool' && item.tool_call_id) { - toolResponseMap.set(item.tool_call_id, item); + if (item.type === 'tool') { + // 使用多种可能的ID字段来匹配工具调用 + const toolCallId = item.tool_call_id || item.id; + if (toolCallId) { + toolResponseMap.set(toolCallId, item); + } } } @@ -127,13 +131,14 @@ export class MessageProcessor { result.additional_kwargs.reasoning_content += chunk.additional_kwargs.reasoning_content; } - // 合并tool_calls + // 合并tool_calls (处理新的数据结构) MessageProcessor._mergeToolCalls(result, chunk); } // 处理AIMessageChunk类型 if (result.type === 'AIMessageChunk') { result.type = 'ai'; + // 将tool_calls从additional_kwargs移到顶层,并确保格式正确 if (result.additional_kwargs?.tool_calls) { result.tool_calls = result.additional_kwargs.tool_calls; } @@ -149,6 +154,7 @@ export class MessageProcessor { * @param {Object} chunk - 当前块 */ static _mergeToolCalls(result, chunk) { + // 1. 处理 additional_kwargs.tool_calls (旧格式,保持兼容性) if (chunk.additional_kwargs?.tool_calls) { if (!result.additional_kwargs) result.additional_kwargs = {}; if (!result.additional_kwargs.tool_calls) result.additional_kwargs.tool_calls = []; @@ -169,6 +175,100 @@ export class MessageProcessor { } } } + + // 2. 处理顶层的 tool_calls (新格式) + if (chunk.tool_calls) { + if (!result.tool_calls) result.tool_calls = []; + + for (const toolCall of chunk.tool_calls) { + // 过滤掉无效的工具调用(没有id或name的空对象) + if (!toolCall.id && !toolCall.name) { + continue; + } + + const existingToolCall = result.tool_calls.find(t => t.id === toolCall.id); + + if (existingToolCall) { + // 合并相同ID的tool call的args + if (toolCall.args && existingToolCall.args !== undefined) { + existingToolCall.args += toolCall.args; + } + } else { + // 添加新的tool call + result.tool_calls.push(JSON.parse(JSON.stringify(toolCall))); + } + } + } + + // 3. 处理 tool_call_chunks (分片的工具调用参数) + if (chunk.tool_call_chunks) { + if (!result.tool_call_chunks) result.tool_call_chunks = []; + + for (const toolCallChunk of chunk.tool_call_chunks) { + // 过滤掉无效的chunk(没有id、name和args的空对象) + if (!toolCallChunk.id && !toolCallChunk.name && !toolCallChunk.args) { + continue; + } + + const existingChunk = result.tool_call_chunks.find( + t => (t.id === toolCallChunk.id || (t.index === toolCallChunk.index && t.index !== null)) + ); + + if (existingChunk) { + // 合并参数字符串 + if (toolCallChunk.args && existingChunk.args !== undefined) { + existingChunk.args += toolCallChunk.args; + } + // 更新工具名称 + if (toolCallChunk.name && !existingChunk.name) { + existingChunk.name = toolCallChunk.name; + } + } else { + // 添加新的chunk + result.tool_call_chunks.push(JSON.parse(JSON.stringify(toolCallChunk))); + } + } + } + + // 4. 同步 tool_call_chunks 到 tool_calls (构建完整的工具调用) + if (result.tool_call_chunks && result.tool_call_chunks.length > 0) { + if (!result.tool_calls) result.tool_calls = []; + + for (const chunk of result.tool_call_chunks) { + if (chunk.name && chunk.args) { + const existingToolCall = result.tool_calls.find(t => t.id === chunk.id); + + if (!existingToolCall) { + // 创建新的完整工具调用 + result.tool_calls.push({ + id: chunk.id, + name: chunk.name, + args: chunk.args, + type: 'tool_call' + }); + } else { + // 更新现有工具调用的参数 + existingToolCall.args = chunk.args; + } + } + } + } + + // 5. 清理无效的工具调用 + if (result.tool_calls) { + result.tool_calls = result.tool_calls.filter(toolCall => { + // 保留有id或有name的工具调用,并且不是空的args对象 + return (toolCall.id || toolCall.name) && + (toolCall.args !== undefined || toolCall.function?.arguments); + }); + } + + // 清理空的tool_call_chunks + if (result.tool_call_chunks) { + result.tool_call_chunks = result.tool_call_chunks.filter(chunk => { + return (chunk.id || chunk.name || chunk.args); + }); + } } /**