说在前面
最近mcp大火,相信很多人已经搭建了自己的mcp
服务,然后通过dify
或者cherry studio
这种工具调用过mcp
服务了,不知道大家是否遇到一个问题,通过dify + mcp
策略插件接入的方式,回答的内容无法流式输出,也就是需要等到所有结果生成完成后一并返回,这是为什么呢?
定位问题
首先看一下前端代码
这个比较直观,主要关注何种情况下会渲染回答。
# 相对路径web\service\base.ts
... existing code ...
if (bufferObj.status === 400 || !bufferObj.event) {
onData('', false, {
conversationId: undefined,
messageId: '',
errorMessage: bufferObj?.message,
errorCode: bufferObj?.code,
})
hasError = true
onCompleted?.(true, bufferObj?.message)
return
}
if (bufferObj.event === 'message' || bufferObj.event === 'agent_message') {
// can not use format here. Because message is splitted.
onData(unicodeToChar(bufferObj.answer), isFirstMessage, {
conversationId: bufferObj.conversation_id,
taskId: bufferObj.task_id,
messageId: bufferObj.id,
})
isFirstMessage = false
}
else if (bufferObj.event === 'agent_thought') {
onThought?.(bufferObj as ThoughtItem)
}
else if (bufferObj.event === 'message_file') {
onFile?.(bufferObj as VisionFile)
}
... existing code ...
大概是可以看出来一些端倪,只有当回复消息的event
是 message
或者agent_message
时,才会赋值answer
,进而渲染回答的textarea
。
然后我们看一下mcp策略的代码,
Github地址在这里。
# 相对路径strategies\ReAct.py
... existing code ...
while run_agent_state and iteration_step <= max_iteration_steps:
# continue to run until there is not any tool call
run_agent_state = False
round_started_at = time.perf_counter()
round_log = self.create_log_message(
label=f"ROUND {iteration_step}",
data={},
metadata={
LogMetadata.STARTED_AT: round_started_at,
},
status=ToolInvokeMessage.LogMessage.LogStatus.START,
)
yield round_log
... existing code ...
通过查看策略的实现,发现全程都是通过日志的方式打印,用于跟踪智能体执行的步骤、耗时,详情等信息,并没有返回event
为message
的信息。
最后看一下实际返回
通过打印调试,证明确实当event:message
的消息返回之后,才会渲染回复信息。
说到最后
以上。