dify 使用Openrouter模型时,多个工具调用的错误工具识别

dohp0rv5  于 2个月前  发布在  其他
关注(0)|答案(4)|浏览(22)

自检

  • 仅用于提交错误报告,如果您想提问,请访问 Discussions
  • 我已在现有问题中搜索 search for existing issues (包括已关闭的问题)。
  • 我确认我使用英文提交此报告(我已阅读并同意 Language Policy )。
  • 请务必使用英文提交问题,否则会被关闭。谢谢!:)
  • 请不要修改此模板 :) 并填写所有必填字段。

Dify版本

0.6.13

云或自托管

自托管(Docker)

重现步骤

在使用代理调用多个工具时,我遇到了Openrouter模型的问题。问题表现为工具名称拼接错误。这意味着,当尝试顺序或同时调用多个工具时,工具名称会被拼接或错误识别。然而,当调用单个工具时,它似乎可以正常工作。

  1. 配置代理以使用Openrouter的模型。
  2. 尝试调用多个工具,例如 current_timesearxng_search
  3. 观察工具识别错误,其中工具名称出现拼接或错误识别(例如, current_time;searxng_search )。

fv2wmkja

fv2wmkja2#

根据我的调试跟踪,我发现Open路由器的模型实际上有两个工具调用响应,但只有一个被记录。

bis0qfac

bis0qfac3#

我没有时间继续追踪断点。我希望熟悉这个领域的人能修复这个bug。非常感谢!

yvfmudvl

yvfmudvl4#

要解决在Dify 0.6.13版本中,通过代理调用多个工具时工具名称拼接错误的问题,需要确保每个工具都能正确识别和单独调用。ToolEngine类的agent_invoke方法负责处理工具调用。以下是agent_invoke方法的一个代码片段,展示了如何调用工具以及如何处理错误:

class ToolEngine:
"""
Tool runtime engine take care of the tool executions.
"""
@staticmethod
def agent_invoke(
tool: Tool, tool_parameters: Union[str, dict],
user_id: str, tenant_id: str, message: Message, invoke_from: InvokeFrom,
agent_tool_callback: DifyAgentCallbackHandler,
trace_manager: Optional[TraceQueueManager] = None
) -> tuple[str, list[tuple[MessageFile, bool]], ToolInvokeMeta]:
"""
Agent invokes the tool with the given arguments.
"""
# check if arguments is a string
if isinstance(tool_parameters, str):
# check if this tool has only one parameter
parameters = [
parameter for parameter in tool.get_runtime_parameters()
if parameter.form == ToolParameter.ToolParameterForm.LLM
]
if parameters and len(parameters) == 1:
tool_parameters = {
parameters[0].name: tool_parameters
}
else:
raise ValueError(f"tool_parameters should be a dict, but got a string: {tool_parameters}")

    # invoke the tool
    try:
        # hit the callback handler
        agent_tool_callback.on_tool_start(
            tool_name=tool.identity.name, 
            tool_inputs=tool_parameters
        )

        meta, response = ToolEngine._invoke(tool, tool_parameters, user_id)
        response = ToolFileMessageTransformer.transform_tool_invoke_messages(
            messages=response, 
            user_id=user_id, 
            tenant_id=tenant_id, 
            conversation_id=message.conversation_id
        )

        return plain_text, message_files, meta
    except ToolProviderCredentialValidationError as e:
        error_response = "Please check your tool provider credentials"
        agent_tool_callback.on_tool_error(e)
    except (
        ToolNotFoundError, ToolNotSupportedError, ToolProviderNotFoundError
    ) as e:
        error_response = f"there is not a tool named {tool.identity.name}"
        agent_tool_callback.on_tool_error(e)
    except (
        ToolParameterValidationError
    ) as e:
        error_response = f"tool parameters validation error: {e}, please check your tool parameters"
        agent_tool_callback.on_tool_error(e)
    except ToolInvokeError as e:
        error_response = f"tool invoke error: {e}"
        agent_tool_callback.on_tool_error(e)
    except ToolEngineInvokeError as e:
        meta = e.args[0]
        error_response = f"tool invoke error: {meta.error}"
        agent_tool_callback.on_tool_error(e)
        return error_response, [], meta
    except Exception as e:
        error_response = f"unknown error: {e}"
        agent_tool_callback.on_tool_error(e)

    return error_response, [], ToolInvokeMeta.error_instance(error_response)

此外,DifyAgentCallbackHandler类提供了处理工具启动、结束和错误事件的方法,这有助于调试并确保每个工具都能正确识别和单独调用。以下是DifyAgentCallbackHandler类中的一个相关代码片段:

class DifyAgentCallbackHandler(BaseModel):
"""Callback Handler that prints to std out."""
color: Optional[str] = ''
current_loop: int = 1

def __init__(self, color: Optional[str] = None) -> None:
    super().__init__()
    """Initialize callback handler."""
    # use a specific color if not specified
    self.color = color or 'green'
    self.current_loop = 1

def on_tool_start(
    self,
    tool_name: str,
    tool_inputs: dict[str, Any],
) -> None:
    """Handle tool start event."""
    print_text("\n[on_tool_start] ToolCall:" + tool_name + "\n" + str(tool_inputs) + "\n", color=self.color)

def on_tool_end(
    self,
    tool_name: str,
    tool_inputs: dict[str, Any],
    tool_outputs: str,
    message_id: Optional[str] = None,
    timer: Optional[Any] = None,
    trace_manager: Optional[TraceQueueManager] = None
) -> None:
    """Handle tool end event."""
    print_text("\n[on_tool_end]\n", color=self.color)
    print_text("Tool: " + tool_name + "\n", color=self.color)
    print_text("Inputs: " + str(tool_inputs) + "\n", color=self.color)
    print_text("Outputs: " + str(tool_outputs)[:1000] + "\n", color=self.color)
    print_text("\n")

    if trace_manager:
        trace_manager.add_trace_task(
            TraceTask(
                TraceTaskName.TOOL_TRACE,
                message_id=message_id,
                tool_name=tool_name,
                tool_inputs=tool_inputs,
                tool_outputs=tool_outputs,
                timer=timer,
            )
        )

def on_tool_error(
    self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
) -> None:
    """Handle tool error event."""
    print_text("\n[on_tool_error] Error: " + str(error) + "\n", color='red')

为了确保每个工具都能正确识别和单独调用,你应该:

  1. 检查工具参数:如果工具需要多个参数,请确保tool_parameters以字典的形式正确格式化。
  2. 回调处理:使用DifyAgentCallbackHandler来处理每个工具调用的启动、结束和错误事件。
  3. 错误处理:妥善处理不同类型的错误,如ToolProviderCredentialValidationErrorToolNotFoundErrorToolParameterValidationError等,以确保正在调用正确的工具,并准确报告任何问题。
  4. 代理日志:利用AgentService类中的get_agent_logs方法来调试和验证工具调用及其参数。

遵循这些步骤,你可以解决工具名称拼接错误的问题,并确保每个工具都能正确识别和单独调用。

相关问题