LangChain Agent 实战:使用框架构建数学计算助手
前言
利用 LangChain 快速实现一个使用 Tool(工具)的 Agent,是构建复杂 AI 应用的关键步骤。Agent 允许大模型自主决定调用哪些工具来完成用户任务,从而突破单纯对话的限制。
LangChain Agent 核心概念
在深入代码之前,建议熟悉以下官方文档资源:
- 内置 Tools:LangChain Tools Integration
- Agent 类型:Agent Types
- Agent Class:Agent Executor API
- Tool Class:BaseTool API
- 自定义 Tools:Custom Tools Guide
自定义 Tool 的实现方式
LangChain 提供了两种主要方式来定义自定义工具。
1. 继承 BaseTool 类
这种方式适合需要更复杂逻辑或状态管理的场景。你需要定义输入参数 Schema 和运行逻辑。
from typing import Type, Optional
from langchain_core.tools import BaseTool
from langchain_core.pydantic_v1 import BaseModel, Field
# 定义输入参数的 Schema
class AddInput(BaseModel):
a: int = Field(description="第一个数字")
b: int = Field(description="第二个数字")
# 定义 Tool 类
class AddTool(BaseTool):
name = "add"
description = "将两个数字相加"
args_schema: Optional[Type[BaseModel]] = AddInput
return_direct: bool = True
def _run(self, a: int, b: int) -> int:
# 实际的业务逻辑
return a + b
# 实例化
tool_instance = AddTool()
print(tool_instance.name)
print(tool_instance.description)
关键点说明:
name:工具的唯一标识,应清晰表达功能。description:对 LLM 至关重要,描述何时使用该工具,可包含 Few-shot 示例。args_schema:定义工具的输入参数结构,帮助 LLM 理解如何传参。_run:实现具体的业务逻辑方法。
2. 使用 Tool 装饰器
对于简单的函数封装,装饰器方式更加简洁高效。
from langchain.tools import tool
@tool
def add(a: int, b: int) -> int:
"""Adds two numbers together"""
return a + b
print(add.name)
print(add.description)
print(add.args)
装饰器会自动处理参数包装和 Description 提取,适合快速原型开发。
Math Agent 完整示例
本章节将实现一个能够执行数学运算的 Agent,包含加法 (add) 和乘法 (multiply) 两个工具。
1. 定义工具与 Toolkit
首先定义基础工具,并使用 Toolkit 进行统一管理。
from typing import List
from langchain_core.tools import BaseToolkit
from langchain.tools import tool
@tool
def add(a: int, b: int) -> int:
"""Adds two numbers together"""
return a + b
@tool
def multiply(a: int, b: int) -> int:
"""Multiplies two numbers together"""
return a * b
class MathToolkit(BaseToolkit):
def get_tools(self) -> List:
return [add, multiply]
2. 初始化 LLM 与 Prompt
配置语言模型和系统提示词。Prompt 的设计直接影响 Agent 的行为边界。
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents import create_tool_calling_agent, AgentExecutor
# 初始化 LLM
llm = ChatOpenAI(model="gpt-4o-2024-05-13", temperature=0)
# 定义 Prompt
prompt = ChatPromptTemplate.from_messages([
("system", """
You are a mathematical assistant. Use your tools to answer questions.
If you do not have a tool to answer the question, say so.
Return only the answers. e.g.
Human: What is 1 + 1?
You: 2
"""),
MessagesPlaceholder("chat_history", optional=True),
("human", "{input}"),
MessagesPlaceholder("agent_scratchpad"),
])
3. 创建 Agent 与 Executor
将 LLM、Tools 和 Prompt 组合成 Agent,并封装为 Executor 以便执行。
# 获取工具列表
tools = MathToolkit().get_tools()
# 创建 Agent
agent = create_tool_calling_agent(llm, tools, prompt)
# 创建 Executor
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# 执行任务
result = agent_executor.invoke({"input": "what is (1 + 3) * 6"})
print(result)
4. 异常处理与边界测试
当用户询问非数学问题时,Agent 应根据 Prompt 设定拒答。
# 测试非数学问题
result = agent_executor.invoke({"input": "What is the time now?"})
print(result["output"])
如果 Prompt 设计得当,LLM 会识别出没有可用的时间查询工具,并告知用户无法回答。
最佳实践与注意事项
- 工具描述准确性:
description字段是 LLM 选择工具的依据,务必详细且准确。 - 参数类型约束:使用 Pydantic 定义
args_schema可以确保传入数据的类型正确,减少幻觉。 - Prompt 工程:通过 System Prompt 明确限制 Agent 的能力范围,防止其过度承诺。
- 错误处理:在生产环境中,建议在
_run方法中添加 try-except 块,捕获工具执行时的异常。 - Token 消耗:复杂的 Agent 交互会增加 Token 消耗,注意监控成本。
总结
本文介绍了如何使用 LangChain 框架自定义 Tool 并构建 Agent。通过继承 BaseTool 或使用 @tool 装饰器,开发者可以快速扩展大模型的能力。结合 AgentExecutor,可以实现自动化任务规划。在实际应用中,需根据具体业务场景优化 Prompt 和工具定义,以确保 Agent 的稳定性和准确性。


