LangChain与Tool Calling:从零构建你的第一个AI代理
·
LangChain与Tool Calling:构建智能代理的实践指南
在人工智能技术快速发展的今天,大型语言模型(LLM)已经展现出惊人的文本理解和生成能力。然而,这些模型本质上仍是"静态"的知识库,缺乏与外部世界交互和执行实际任务的能力。这正是Tool Calling技术要解决的核心问题——让AI不仅会"说",还能"做"。
1. 理解Tool Calling的核心概念
Tool Calling(工具调用)是一种让大型语言模型能够识别用户意图并调用外部函数或API的技术机制。它弥合了语言模型的认知能力与实际执行能力之间的鸿沟,是构建智能代理(Agent)的基础。
关键特性对比:
| 特性 | 传统LLM | 支持Tool Calling的LLM |
|---|---|---|
| 知识范围 | 训练数据截止点前的静态知识 | 可获取实时外部信息 |
| 计算能力 | 近似计算,可能出错 | 精确调用计算工具 |
| 执行能力 | 仅文本生成 | 可操作外部系统和API |
| 响应方式 | 直接生成回答 | 可能返回工具调用指令 |
Tool Calling的工作流程通常包含三个关键阶段:
- 意图识别:模型分析用户请求,判断是否需要调用工具
- 参数提取:如需调用,生成结构化参数
- 结果整合:将工具返回结果转化为自然语言响应
# 简化的Tool Calling流程示例
def process_query(query):
# 第一阶段:意图识别
if needs_tool(query):
tool_name, params = identify_tool_and_params(query)
# 第二阶段:执行工具
result = execute_tool(tool_name, params)
# 第三阶段:结果整合
return generate_response(result)
else:
return generate_direct_response(query)
2. LangChain框架的核心优势
LangChain作为当前最流行的LLM应用开发框架,为Tool Calling提供了优雅的抽象和丰富的工具集成。相比直接使用底层API,LangChain带来了几个显著优势:
- 多模型兼容性:统一接口对接不同供应商的模型
- 工具管理标准化:简化工具的定义、注册和调用流程
- 对话状态维护:自动管理复杂的多轮交互上下文
- 组合式开发:支持将多个工具串联成复杂工作流
典型开发流程:
- 定义工具函数
- 创建工具描述Schema
- 绑定到语言模型
- 构建代理(Agent)工作流
- 处理用户交互
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
# 第一步:定义工具
@tool
def get_weather(city: str) -> str:
"""获取指定城市的当前天气情况"""
# 实际实现会调用天气API
return f"{city}天气:晴,25°C"
# 第二步:初始化模型
model = ChatOpenAI(model="gpt-3.5-turbo")
# 第三步:绑定工具
model_with_tools = model.bind_tools([get_weather])
# 第四步:处理查询
response = model_with_tools.invoke("北京今天天气如何?")
3. 实战:构建数学计算代理
让我们通过一个完整的例子,构建能够处理数学运算的AI代理。这个代理将能够理解自然语言描述的计算问题,并返回精确的结果。
3.1 环境准备
首先确保安装必要依赖:
pip install langchain langchain-openai python-dotenv
创建.env文件存储API密钥:
OPENAI_API_KEY=your_api_key_here
3.2 定义计算工具
我们将创建支持四则运算的工具集:
from langchain_core.tools import tool
from pydantic import BaseModel, Field
class MathInput(BaseModel):
a: float = Field(description="第一个操作数")
b: float = Field(description="第二个操作数")
@tool("calculator-add", args_schema=MathInput)
def add(a: float, b: float) -> float:
"""两个数字相加"""
return a + b
@tool("calculator-subtract", args_schema=MathInput)
def subtract(a: float, b: float) -> float:
"""两个数字相减"""
return a - b
@tool("calculator-multiply", args_schema=MathInput)
def multiply(a: float, b: float) -> float:
"""两个数字相乘"""
return a * b
@tool("calculator-divide", args_schema=MathInput)
def divide(a: float, b: float) -> float:
"""两个数字相除"""
if b == 0:
return "错误:除数不能为零"
return a / b
3.3 构建完整代理
将工具集成到对话代理中:
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
import os
from dotenv import load_dotenv
load_dotenv()
# 初始化模型
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
# 准备工具列表
tools = [add, subtract, multiply, divide]
# 定义提示模板
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个专业的数学助手,请根据用户问题选择合适的计算工具。"),
("placeholder", "{chat_history}"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}")
])
# 创建代理
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# 运行代理
result = agent_executor.invoke({"input": "请计算3.14乘以15.7的结果"})
print(result["output"])
3.4 进阶:处理复杂表达式
为了让代理能处理更复杂的数学表达式,我们可以添加一个支持eval的计算器:
from typing import Dict, Any
import ast
import operator as op
@tool("advanced-calculator")
def calculator(expression: str) -> float:
"""计算数学表达式,支持加减乘除和括号"""
allowed_operators = {
ast.Add: op.add,
ast.Sub: op.sub,
ast.Mult: op.mul,
ast.Div: op.truediv
}
def eval_expr(node):
if isinstance(node, ast.Num):
return node.n
elif isinstance(node, ast.BinOp):
return allowed_operators[type(node.op)](
eval_expr(node.left),
eval_expr(node.right)
)
else:
raise ValueError("不支持的运算类型")
try:
tree = ast.parse(expression, mode='eval').body
return eval_expr(tree)
except Exception as e:
return f"计算错误:{str(e)}"
注意:实际生产环境中应对eval进行严格的安全限制,此处仅为演示用途。
4. 调试与优化技巧
开发Tool Calling应用时,以下几个技巧能显著提升开发效率:
调试工具:
- 使用
verbose=True开启详细日志 - 检查中间生成的工具调用参数
- 验证工具描述是否清晰准确
性能优化:
- 为复杂工具添加缓存机制
- 对耗时操作实现异步调用
- 合理设置超时时间
提示工程技巧:
- 工具描述应明确使用场景
- 参数描述要具体清晰
- 示例能显著提升工具调用准确率
# 优化后的工具描述示例
@tool
def get_stock_price(symbol: str) -> float:
"""
获取股票当前价格。当用户询问某支股票的最新行情时使用此工具。
Args:
symbol: 股票代码,如'AAPL'代表苹果公司
Returns:
该股票的当前市场价格(美元)
"""
# 实现代码...
构建高效的AI代理不仅需要技术实现,更需要深入理解用户需求和使用场景。通过LangChain的Tool Calling功能,开发者可以快速将语言模型的认知能力转化为实际的问题解决能力,创造出真正有价值的智能应用。
更多推荐


所有评论(0)