LangChain框架入门17: 手把手教你创建LLM工具

大语言模型(LLM)是基于训练数据进行预测并生成结果的,它无法掌握训练数据之外的知识。这一点在前面的文章中已经多次提到,通过 RAG 检索的方式,可以在一定程度上缓解这一问题。

但如果我们希望大模型获取最新的时事信息呢?或者让它查找"北京最好吃的五家餐馆"的地理位置信息?又或者要求它完成一套复杂的数学计算?这些需求仅依靠大语言模型本身的能力显然无法解决。

为此,LangChain 提供了 Tools 组件,可以通过创建自定义工具的方式,让 LLM 调用外部能力:例如,获取时事信息时调用搜索工具,查询地理位置时对接高德地图等 API,执行复杂计算时也能编写专门的工具。有了工具调用,AI 应用在解决实际问题上的能力就能得到进一步提升。

在构建 LLM 对象时,可以将工具列表绑定到模型上。这样,LLM 就能够获取到这些工具的名称、描述和参数定义,并以此作为上下文信息来判断是否需要调用工具。如果需要,它会请求调用一个或多个工具,并传入相应的参数,工具调用流程图如下:

当接收到调用指令和参数后,工具会执行相应逻辑并返回结果。随后,大语言模型会结合工具的输出,对用户的提问生成最终回答。这就是LLM工具调用的基本流程。

要实现LLM工具调用,第一步就是工具的创建。本文将会详细介绍在 LangChain 中如何创建工具,在后续文章中,我们会进一步展开,讲解工具调用的完整流程。

文中所有示例代码:github.com/wzycoding/l...

一、工具是什么

LLM 和工具之间的关系好比:大语言模型像是"大脑",工具就像人的"四肢"。大脑可以对四肢发出指令,而 LLM 则会根据用户的提问来决定调用哪些工具。

所谓工具,其实就是供 LLM 调用的程序,可以是实现特定功能的类或函数,也可以是对外部 API 的封装。

一个工具通常需要包含以下几个部分:

  • 工具的名称
  • 工具的功能描述
  • 工具入参的 JSON Schema
  • 执行工具逻辑的函数

LangChain 中,支持三种方式来创建工具:

  • 函数方式
  • 通过 Runnables 创建
  • 继承 BaseTool

下面将分别介绍这三种工具创建方式。

二、通过函数创建工具

通过函数方式创建工具时,需要配合 @tool 注解,将函数转换为工具。其中,第一个参数默认为工具名称,args_schema 用于指定入参结构,return_direct 表示工具调用完成后是否直接将结果传递给大模型:当值为 True 时,结果会直接返回;当值为 False 时,结果会先经过大模型加工后再返回。示例如下:

python 复制代码
from langchain_core.tools import tool
from pydantic.v1 import Field, BaseModel
​
​
class AddNumberInput(BaseModel):
    num1: int = Field(description="第一个数")
    num2: int = Field(description="第二个数")
​
​
@tool("add-tool", args_schema=AddNumberInput, return_direct=True)
def add(num1: int, num2: int):
    """两数相加"""
    return num1 + num2
​
​
print(f"工具名称:{add.name}")
print(f"工具描述:{add.description}")
print(f"工具参数:{add.args}")
print(f"是否直接返回:{add.return_direct}")
​
print("1+1=" + str(add.invoke({"num1": 1, "num2": 1})))

执行结果如下:

python 复制代码
工具名称:add-tool
工具描述:两数相加
工具参数:{'num1': {'title': 'Num1', 'description': '第一个数', 'type': 'integer'}, 'num2': {'title': 'Num2', 'description': '第二个数', 'type': 'integer'}}
是否直接返回:True
1+1=2

除了使用注解的方式,还可以通过 StructuredTool 来创建工具。StructuredTool.from_function 类方法相比 @tool 注解提供了更多配置项,并且不需要额外编写代码。其中,func 参数用于传入同步执行的函数,coroutine 参数则用于传入异步执行的函数,其余参数的作用与前面介绍的相同。示例如下:

python 复制代码
import asyncio
​
from langchain_core.tools import StructuredTool
from pydantic.v1 import BaseModel, Field
​
​
class AddNumberInput(BaseModel):
    """加法工具入参"""
    num1: int = Field(description="第一个数")
    num2: int = Field(description="第二个数")
​
​
def add(num1: int, num2: int):
    """两数相加"""
    return num1 + num2
​
​
async def async_add(num1: int, num2: int):
    """两数相加"""
    return num1 + num2
​
​
add_tool = StructuredTool.from_function(
    func=add,
    coroutine=async_add,
    name="add_tool",
    description="两数相加",
    args_schema=AddNumberInput,
    return_direct=True,
)
​
print(f"工具名称:{add_tool.name}")
print(f"工具描述:{add_tool.description}")
print(f"工具参数:{add_tool.args}")
print(f"是否直接返回:{add_tool.return_direct}")
​
# 同步调用工具
print("1+1=" + str(add_tool.invoke({"num1": 1, "num2": 1})))
​
​
# 异步调用工具
async def async_main():
    result = await add_tool.ainvoke({"num1": 2, "num2": 5})
    print("2+5=" + str(result))
​
​
asyncio.run(async_main())

执行结果如下:

python 复制代码
工具名称:add_tool
工具描述:两数相加
工具参数:{'num1': {'title': 'Num1', 'description': '第一个数', 'type': 'integer'}, 'num2': {'title': 'Num2', 'description': '第二个数', 'type': 'integer'}}
是否直接返回:True
1+1=2
2+5=7

三、通过Runnables创建工具

通过可运行组件(Runnable)的 as_tool() 方法也可以创建工具。由于由多个可运行组件组成的链(Chain)本身也是一个 Runnable,因此可以直接调用 chain.as_tool() 方法,将整个链包装成一个工具。示例如下:

python 复制代码
import dotenv
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from pydantic.v1 import BaseModel, Field
​
# 读取env配置
dotenv.load_dotenv()
​
​
class RandomInput(BaseModel):
    """生成随机数入参"""
    count: int = Field(description="生成随机数个数")
​
​
# 1.创建提示词模板
prompt = ChatPromptTemplate.from_template("请帮我生成{count}个100以内随机数,只返回随机数本身就好")
​
# 2.构建GPT-3.5模型
llm = ChatOpenAI(model="gpt-3.5-turbo")
​
# 3.创建输出解析器
parser = StrOutputParser()
​
# 4.执行链
chain = prompt | llm | parser
​
random_tool = chain.as_tool(name="random_tool", description="生成100以内随机数", args_schema=RandomInput)
print("生成随机数:" + str(random_tool.invoke({"count": 10})))

执行结果:

python 复制代码
生成随机数:27, 63, 84, 12, 95, 41, 55, 73, 38, 9

四、通过继承BaseTool类创建工具

还可以通过继承 BaseTool 来创建自定义工具。这种方式的自由度最高,也更加灵活。示例如下:创建 AddNumberTool 类继承 BaseTool,并指定工具相关参数,同时重写 _run() 方法,在方法中实现具体的工具逻辑。

python 复制代码
from langchain_core.tools import BaseTool
from pydantic.v1 import BaseModel, Field
​
​
class AddNumberInput(BaseModel):
    """加法工具入参"""
    num1: int = Field(description="第一个数")
    num2: int = Field(description="第二个数")
​
​
class AddNumberTool(BaseTool):
    """加法工具"""
    name = "add_number_tool"
    description = "两数相加工具"
    args_schema = AddNumberInput
​
    def _run(self, num1: int, num2: int) -> int:
        return num1 + num2
​
​
add_number_tool = AddNumberTool()
​
print(f"工具名称:{add_number_tool.name}")
print(f"工具描述:{add_number_tool.description}")
print(f"工具参数:{add_number_tool.args}")
print(f"是否直接返回:{add_number_tool.return_direct}")
​
print("1+1=" + str(add_number_tool.invoke({"num1": 1, "num2": 1})))

执行结果:

python 复制代码
工具名称:add_number_tool
工具描述:两数相加工具
工具参数:{'num1': {'title': 'Num1', 'type': 'integer'}, 'num2': {'title': 'Num2', 'type': 'integer'}}
是否直接返回:False
1+1=2

五、总结

通过工具,LLM 这个"超级大脑"有了四肢,甚至可以配备各种各样的"武器"。这些"武器"就是提供给 LLM 的工具。有了工具,LLM 不再只是一个聊天助手,而是能够真正解决问题的助手。它可以根据用户的提问内容做出判断,决定需要调用哪些工具,并传递相应的参数。

LangChain 中,创建工具的方式有多种,不同方式适用于不同场景:通过函数创建工具,适合实现简单功能;将 Chain 包装成工具,方便已有逻辑的复用;如果需求比较复杂,则可以通过继承 BaseTool 类的方式,实现更灵活的工具。

通过本文的介绍,相信你已经理解了为什么需要工具,以及 LLM 如何进行工具调用。除此之外,我们还重点介绍了多种工具创建方式。在下一篇文章中,将会详细讲解如何让 LLM 实际完成工具调用,欢迎持续关注。

相关推荐
二进制星轨16 分钟前
Transofrmer架构详解与PyTorch实现(附代码讲解)
人工智能·pytorch·python
生而为虫37 分钟前
02.第一个Python程序
开发语言·python
视觉AI1 小时前
如何查看 Linux 下正在运行的 Python 程序是哪一个
linux·人工智能·python
数据智能老司机2 小时前
Spring AI 实战——提交用于生成的提示词
spring·llm·ai编程
猫头虎2 小时前
永久免费白嫖多个域名,一键托管Cloudflare,免费申请SSL加密证书,轻松建站、搭建线路伪装
服务器·开发语言·网络·数据库·python·网络协议·ssl
沙虫一号2 小时前
线上python问题排查思路
后端·python
数据智能老司机2 小时前
Spring AI 实战——评估生成结果
spring·llm·ai编程
B站_计算机毕业设计之家3 小时前
深度学习:Yolo水果检测识别系统 深度学习算法 pyqt界面 训练集测试集 深度学习 数据库 大数据 (建议收藏)✅
数据库·人工智能·python·深度学习·算法·yolo·pyqt
该用户已不存在3 小时前
免费的 Vibe Coding 助手?你想要的Gemini CLI 都有
人工智能·后端·ai编程