首页 / 文章 / 使用 LangChain 的你的第一个工具型 AI 智能体

使用 LangChain 的你的第一个工具型 AI 智能体

用 Python 构建一个小型 LangChain 数学智能体:初始化聊天模型,注册工具,让大语言模型选择要调用的函数,并观察多步骤的工具使用过程。

1062 词

一个简短的 Python + LangChain 实践可以构建出一个类似计算器的智能体,它在需要时能够调用加法、减法、乘法、除法或平方根等辅助函数。

算术运算只是附带的。真正有价值的是观察大语言模型如何接收这些可调用的辅助函数,并决定在哪个步骤调用哪个辅助函数。

该智能体能够处理的示例问题:

将 25 乘以 4,再取 144 的平方根,最后将得到的结果乘以 5。

无需手动编写具体的计算步骤,只需注册多个辅助函数即可。模型会根据用户的表述从中选择合适的函数。

1. 初始化模型

首先需要构建聊天模型:

from langchain.chat_models import init_chat_model

model = init_chat_model("openai:gpt-4o-mini")

目前还不存在类似智能体的结构——只有一個能够读写文本的模型。

2. 注册可调用的辅助函数

当智能体能够超越单纯的文本生成并调用应用程序功能时,它们便变得实用起来。

定义五个最基本的辅助函数:

from langchain.tools import tool
import math

@tool
def add(a: float, b: float) -> float:
    """Add two numbers."""
    return a + b

@tool
def subtract(a: float, b: float) -> float:
    """Subtract two numbers."""
    return a - b


@tool
def multiply(a: float, b: float) -> float:
    """Multiply two numbers."""
    return a * b


@tool
def divide(a: float, b: float) -> float:
    """Divide two numbers."""
    if b == 0:
        raise ValueError("Cannot divide by zero.")
    return a / b


@tool
def square_root(a: float) -> float:
    """Calculate the square root of a number."""
    if a < 0:
        raise ValueError("Cannot calculate square root of a negative number.")
    return math.sqrt(a)

使用@tool标记可将每个函数以智能体运行时能够理解的形式呈现出来。

有两个要素用于引导模型:

  1. 带注释的参数可指定所需的参数类型。
a: float
b: float
  1. 文档字符串会提供通俗易懂的描述,模型在判断相关性时会参考这些描述。

对于智能体工具而言,函数的叙述性描述属于控制界面的一部分,而非装饰内容。

"""Multiply two numbers."""

3. 连接智能体

将这些辅助函数绑定到模型上:

from langchain.agents import create_agent

agent = create_agent(
    model=model,
    tools=[
        add,
        subtract,
        multiply,
        divide,
        square_root
    ],
)

这样一来,聊天模型就可以作为智能体来运行,而不仅仅是一个一次性回答工具。

典型步骤包括:

  1. 解析用户的意图
  • 判断是否需要辅助工具
  • 选择辅助工具
  • 提供参数
  • 使用辅助工具的返回值
  • 判断是否需要进一步操作
  • 输出最终回复
  • 简而言之:

    User
     ↓
    Agent
     ↓
    Should I use a tool?
     ↓
    Choose tool
     ↓
    Execute tool
     ↓
    Get result
     ↓
    Final response
    

    多步骤问题可能会重复该循环。

    4. 执行一次运行

    只需一个简单的封装结构即可驱动其运行:

    def run_agent(question: str):
        """Run the agent and print the execution trace."""
    
        print(f"User: {question}")
    
        result = agent.invoke({
            "message": [("user", question)],
        })
    
        print("Agent:", result)
    

    通过一个简单的问题来调用它:

    run_agent("What is 25 multiplied by 4?")
    

    注意这里并没有“调用multiply”这样的指令。

    仅提供了辅助工具的列表。

    根据表述及每个辅助工具的描述,模型判定乘法是合适的操作。

    5. 连续使用多个辅助工具

    尝试使用复合提示:

    run_agent(
        "Calculate the square root of 144 and multiply the result by 5."
    )
    

    需要执行两个操作。

    其概念流程如下:

    User:
    
    Calculate √144 × 5
            ↓
    Agent chooses square_root
            ↓
    square_root(144)
            ↓
    12
            ↓
    Agent chooses multiply
            ↓
    multiply(12, 5)
            ↓
    60
            ↓
    Final answer
    

    那种循环——选择、调用、观察、再次选择——正是工具使用型智能体的核心所在。

    应用代码无需预先编码完整的操作顺序。

    模型可以根据剩余的辅助工具和对话状态推导出下一步该做什么。

    6. 与普通大语言模型的对比

    在没有工具的情况下,模型可能会直接输出“答案是60”这样的文本。

    当有注册好的辅助工具时,它就可以将数值计算任务交给真正的函数来处理。

    控制权的转移

    仅文本路径:用户 → 模型 → 答案字符串

    与之相对的是:

    Tool-using agent
    
    User
      ↓
    LLM
      ↓
    Choose tool
      ↓
    Execute code
      ↓
    Observe result
      ↓
    LLM
      ↓
    Answer
    

    模型不再需要亲自执行所有的计算。

    它只需提出“下一步应执行哪个操作”;具体有哪些操作以及如何执行则由应用程序决定。

    7. 需要保护的边界

    计算器只是一种教学工具而已。

    这一稳健的设计思路在于将模型判断与执行权限分开。

    自然语言理解与动作选择非常适合由大语言模型处理。

    这些动作的实际执行则应在您可控的 Python 环境中完成。

    模型可能会认为需要这种分离机制。

    具体的分离实现及其带来的副作用由您的流程负责处理。

    可以用领域特定的操作来替代那些简单的数学计算工具,例如:

    get_customer()
    search_transactions()
    create_report()
    send_email()
    query_database()
    get_weather()
    create_ticket()
    

    这样一来,同样的协调模式就开始具备生产级智能体设计的特征。

    练习总结

    通过几个模块的配合,我们构建出了一个能够:

    • 理解自由形式的提问
    • 从多个已注册的工具中选择合适的工具
    • 正确传递参数
    • 在单次会话中组合使用多个工具
    • 将工具的输出反馈到后续的推理过程中
    的智能体。

  • 在流程完成后回复用户
  • 简而言之:这是一种能够选择并执行操作的LLM,而非仅能生成文本的模型。