1. LangChain实战:工具调用与结构化输出的深度解析
作为一名长期从事AI应用开发的工程师,我深刻体会到LangChain在构建智能应用时的价值。今天我将分享LangChain中两个最实用的功能:工具调用和结构化输出,这些技术能让你的AI应用从简单的"聊天机器人"升级为真正能"干活"的智能助手。
1.1 工具调用:让AI拥有"手脚"
工具调用(Tool Calling)是LangChain最强大的功能之一,它允许AI模型调用外部函数或API来完成特定任务。想象一下,当用户询问天气时,LLM本身并不知道实时天气数据,但通过工具调用,它可以连接天气API获取最新信息。
1.1.1 工具创建的三种方式
在LangChain中,我们可以用三种方式创建工具:
- 最简单的方式:@tool装饰器
python复制@tool
def add(a: int, b: int) -> int:
"""两个数字相加"""
return a + b
这种方式适合简单的工具函数,只需添加@tool装饰器和类型注解即可。
- 进阶方式:@tool + Pydantic参数结构
python复制from pydantic import BaseModel
class AddInput(BaseModel):
a: int = Field(description="第一个加数")
b: int = Field(description="第二个加数")
@tool(args_schema=AddInput)
def add(a: int, b: int) -> int:
return a + b
这种方式参数更清晰,能写详细说明,适合需要明确参数含义的场景。
- 最灵活的方式:继承BaseTool
python复制from langchain.tools import BaseTool
class AddTool(BaseTool):
name = "add_tool"
description = "两个数字相加"
def _run(self, a: int, b: int):
return a + b
这种方式适合复杂或异步操作,比如调用外部API,你可以完全控制工具的行为。
提示:对于简单的工具,推荐使用@tool装饰器;需要复杂参数验证时用Pydantic;当工具需要特殊处理(如异步调用)时,才需要继承BaseTool。
1.1.2 本地自定义工具实战
让我们通过一个完整示例看看如何创建和使用本地工具:
python复制from langchain_core.tools import tool
@tool
def sum_to_n(n: int) -> int:
"""计算从0累加到n的结果"""
return sum(range(n+1))
# 初始化模型并绑定工具
from langchain.chat_models import ChatDeepSeek
llm = ChatDeepSeek(
model_name="deepseek-chat",
api_key="your-api-key",
temperature=0.7
)
bound_llm = llm.bind_tools([sum_to_n])
# 工具调用流程
from langchain_core.messages import HumanMessage, ToolMessage
# 用户提问
message = [HumanMessage(content="计算从0加到100的结果")]
# 模型决定调用工具
ai_message = bound_llm.invoke(message)
# 执行工具调用
if ai_message.tool_calls:
tool_call = ai_message.tool_calls[0]
result = sum_to_n.invoke(tool_call["args"])
tool_message = ToolMessage(
content=str(result),
tool_call_id=tool_call["id"]
)
# 获取最终回复
final_msg = bound_llm.invoke([*message, ai_message, tool_message]).content
print(final_msg) # 输出: "从0加到100的结果是5050"
这个例子展示了完整的工具调用流程:
- 定义工具(sum_to_n)
- 绑定工具到模型
- 模型分析用户输入并决定调用工具
- 执行工具调用
- 将结果返回给模型生成最终回复
1.1.3 第三方工具集成:以Tavily搜索为例
LangChain的强大之处在于它能轻松集成各种第三方工具。让我们以Tavily搜索为例:
python复制from langchain_tavily import TavilySearch
# 创建搜索工具
tavily_tool = TavilySearch(
max_results=3,
tavily_api_key="your-api-key"
)
# 绑定工具到模型
bound_llm = llm.bind_tools([tavily_tool])
# 多轮工具调用示例
messages = [
HumanMessage(content="2026年3月2日北京天气情况")
]
for _ in range(3): # 最多尝试3次
ai_message = bound_llm.invoke(messages)
messages.append(ai_message)
if not ai_message.tool_calls:
print(ai_message.content)
break
# 执行工具调用
for tool_call in ai_message.tool_calls:
result = tavily_tool.invoke(tool_call["args"])
messages.append(
ToolMessage(
content=str(result),
tool_call_id=tool_call["id"]
)
)
在实际项目中,我发现多轮工具调用特别有用。有时AI需要多次搜索或组合多个工具的结果才能回答复杂问题。设置调用次数限制(如3次)可以防止无限循环。
1.2 结构化输出:让AI的回答更规范
结构化输出(Structured Output)是另一个改变游戏规则的
