跳到主要内容
LangChain 实战:工具调用与结构化输出 | 极客日志
Python AI 算法
LangChain 实战:工具调用与结构化输出 深入讲解 LangChain 中的工具调用与结构化输出技术。涵盖三种工具创建方式及本地、第三方工具集成流程,详解 Pydantic、TypedDict、JSON Schema 三种结构化输出方案及其动态类型选择技巧。结合实际案例展示如何提升 AI 执行能力与数据规范性,包括简历解析、意图识别及智能助手三大场景,帮助开发者构建更可靠的 AI 应用。
咸鱼开飞机 发布于 2026/4/9 更新于 2026/5/22 15 浏览LangChain 实战:工具调用与结构化输出
工具调用是 LangChain 的核心功能之一,允许 AI 模型调用外部函数或 API 来完成特定任务。比如获取实时天气或查询数据库,LLM 本身无法直接访问这些信息,借助工具就能通过外部服务完成。
工具创建方式
1. 直接使用 @tool 装饰函数
最简单的方式,适合小型工具。
from langchain_core.tools import tool
@tool
def add (a: int , b: int ) -> int :
return a + b
2. 使用 @tool + Pydantic 自定义参数结构
参数更清晰,能写详细说明。
@tool(args_schema=AddInput )
def add (a: int , b: int ) -> int :
return a + b
3. 继承 BaseTool 写类
最灵活,适合复杂或异步操作(比如调 API)。
from langchain_core.tools import BaseTool
class AddTool (BaseTool ):
name = "add"
description = "Adds two numbers"
def _run (self, a: int , b: int ):
return a + b
本地自定义工具实战
定义工具
使用 @tool 装饰器定义一个本地工具,注意函数必须有类型注解,文档字符串会被模型用来理解工具的功能。
from langchain_core.tools tool
( ) -> :
total =
i (n + ):
total += i
total
import
@tool
def
sum_to_n
n: int
int
"""计算从 0 累加到 n 的结果"""
0
for
in
range
1
return
绑定工具到模型 from langchain.chat_models import init_chat_model
llm = init_chat_model(
model="deepseek-chat" ,
model_provider="deepseek" ,
api_key="your-api-key" ,
temperature=0.7 ,
max_tokens=8192 ,
)
bound_llm = llm.bind_tools([sum_to_n])
工具调用流程 模型会决定是否调用工具,执行结果需包装为 ToolMessage 返回。
from langchain_core.messages import HumanMessage, SystemMessage, ToolMessage
messages = [
SystemMessage(content="你是一个数学助手。当用户给你一个数字 n 时,使用 sum_to_n 工具计算从 0 累加到 n 的结果。" ),
HumanMessage(content="10" ),
]
ai_message = bound_llm.invoke(messages)
messages.append(ai_message)
for tool_call in ai_message.tool_calls:
if tool_call["name" ] == "sum_to_n" :
result = sum_to_n.invoke(tool_call["args" ])
messages.append(
ToolMessage(content=str (result), tool_call_id=tool_call["id" ])
)
final_msg = bound_llm.invoke(messages).content
print (final_msg)
工作流程: 用户输入 → AI 分析 → 决定调用工具 → 执行工具 → 返回结果 → AI 生成最终回答。
AI 响应结构解析 当模型决定调用工具时,ai_message 包含关键信息:
{
'content' : '我来计算从 0 累加到 10 的结果。' ,
'tool_calls' : [
{
'name' : 'sum_to_n' ,
'args' : {'n' : 10 },
'id' : 'call_00_xxx' ,
'type' : 'tool_call'
}
],
'response_metadata' : {
'token_usage' : {...},
'model_name' : 'deepseek-chat' ,
'finish_reason' : 'tool_calls'
}
}
注意 ai_message 是经过 LangChain 框架整合后的响应,必须使用 ToolMessage 包装工具执行结果并提供 tool_call_id。
第三方工具集成 以 Tavily 搜索为例,通常需要 API Key,参数名需正确。
集成与多轮调用 from langchain_tavily import TavilySearch
tavily_tool = TavilySearch(max_results=4 , tavily_api_key="your-tavily-api-key" )
bound_llm = llm.bind_tools([tavily_tool])
messages = [
SystemMessage(content="你是一个天气助手。使用 tavily_search 工具搜索天气情况。" ),
HumanMessage(content="2026 年 3 月 2 日北京天气情况" ),
]
max_rounds = 3
for round_num in range (1 , max_rounds + 1 ):
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" ])
tool_message = ToolMessage(
content=str (result), tool_call_id=tool_call["id" ]
)
messages.append(tool_message)
结构化输出 结构化输出允许模型返回符合特定格式的数据,而不是纯文本。这对于数据提取、API 响应生成等场景非常有用。
1. Pydantic BaseModel(推荐)
定义模型 继承 BaseModel,使用 Field() 添加字段描述,支持类型验证和数据校验。
from pydantic import BaseModel, Field
class TestOutput (BaseModel ):
test: str = Field(description="这个城市现在的详细天气情况" )
test2: str = Field(description="城市名称" )
test3: str = Field(description="在这个城市出生的一个著名名人" )
绑定与调用 from langchain_deepseek import ChatDeepSeek
llm_deepseek = ChatDeepSeek(
model_name="deepseek-chat" ,
api_key="your-api-key" ,
base_url="https://api.deepseek.cn/v1" ,
)
struct_output_model = llm_deepseek.with_structured_output(TestOutput)
result = struct_output_model.invoke("上海" )
print (f"天气:{result.test} " )
print (f"城市:{result.test2} " )
优点: 类型安全,IDE 有完整代码提示,自动数据验证,支持嵌套结构。
2. TypedDict from typing import TypedDict, Annotated
class TestOutputDict (TypedDict ):
weather: Annotated[str , "这个城市现在的详细天气情况" ]
city_name: Annotated[str , "城市名称" ]
population: Annotated[int , "城市人口数量(万人)" ]
struct_output_model_dict = llm_deepseek.with_structured_output(TestOutputDict)
result_dict = struct_output_model_dict.invoke("上海" )
print (f"人口:{result_dict['population' ]} 万人" )
缺点: 类型检查较弱,不支持 Field() 的高级功能。
3. JSON Schema import json
json_schema = {
"title" : "CityInfo" ,
"description" : "城市信息的 JSON 格式" ,
"type" : "object" ,
"properties" : {
"city" : {"type" : "string" , "description" : "城市名称" },
"weather" : {"type" : "string" , "description" : "当前天气情况" },
"attractions" : {
"type" : "array" ,
"items" : {"type" : "string" },
"description" : "城市的著名景点列表"
},
"gdp" : {"type" : "number" , "description" : "城市 GDP(亿元)" }
},
"required" : ["city" , "weather" , "attractions" , "gdp" ]
}
struct_output_model_json = llm_deepseek.with_structured_output(json_schema)
result_json = struct_output_model_json.invoke("北京" )
print (json.dumps(result_json, ensure_ascii=False , indent=2 ))
4. 可选结构化输出(动态类型选择) 当你需要模型根据用户输入自动选择返回不同类型的结构化数据时,可以使用此方法。这在智能客服、多功能 API 场景中非常有用。
from pydantic import BaseModel, Field
from typing import Literal
class PersonInfo (BaseModel ):
name: str = Field(description="姓名" )
age: int = Field(description="年龄" )
class CityInfo (BaseModel ):
city: str = Field(description="城市名称" )
population: int = Field(description="人口(万人)" )
class NormalAnswer (BaseModel ):
answer: str = Field(description="根据用户的提问正常答复的内容" )
class Response (BaseModel ):
type : Literal ["person" , "city" , "normal" ] = Field(
description="响应类型:person 表示人物,city 表示城市,normal 表示普通回答"
)
person: PersonInfo | None = Field(default=None )
city: CityInfo | None = Field(default=None )
normal: NormalAnswer | None = Field(default=None )
model = llm_deepseek.with_structured_output(Response)
result1 = model.invoke("上海" )
if result1.type == "city" :
print (f"城市:{result1.city.city} " )
优势: 灵活性高,一个接口处理多种类型的请求,类型明确,易于扩展。
三大实际应用场景
场景 1:作为信息提取器 from pydantic import BaseModel, Field
class Education (BaseModel ):
school: str = Field(description="学校名称" )
degree: str = Field(description="学位" )
major: str = Field(description="专业" )
class ResumeInfo (BaseModel ):
name: str = Field(description="姓名" )
phone: str = Field(description="电话" )
education: list [Education] = Field(description="教育经历列表" )
skills: list [str ] = Field(description="技能列表" )
model = llm_deepseek.with_structured_output(ResumeInfo)
resume_text = "张三,电话:138****1234..."
result = model.invoke(f"请从以下简历中提取信息:\n{resume_text} " )
print (f"姓名:{result.name} " )
print (f"技能:{', ' .join(result.skills)} " )
关键优势: 自动化数据录入,格式标准化,提高准确性。
场景 2:作为提示词增强 帮助 AI 更好理解用户意图,将模糊需求转换为明确的结构化指令。
from typing import Literal
class SearchIntent (BaseModel ):
intent_type: Literal ["informational" , "transactional" , "navigational" ] = Field(
description="意图类型"
)
keywords: list [str ] = Field(description="提取的关键词列表" )
filters: dict [str , str ] = Field(description="筛选条件" )
model = llm_deepseek.with_structured_output(SearchIntent)
user_query = "我想买个性价比高的笔记本电脑,预算 5000 左右"
intent = model.invoke(f"分析以下用户需求:{user_query} " )
if intent.intent_type == "transactional" :
search_params = {
"category" : "笔记本电脑" ,
"price_range" : intent.filters.get("price_range" , "" ),
"keywords" : intent.keywords
}
print (f"执行搜索:{search_params} " )
场景 3:与 Tool 联合使用 结构化输出与工具调用结合,实现智能决策 + 精准执行。
from langchain_tavily import TavilySearch
class WeatherResult (BaseModel ):
location: str = Field(description="地点" )
temperature: str = Field(description="温度范围" )
weather: str = Field(description="天气状况" )
tavily_tool = TavilySearch(max_results=4 , tavily_api_key="your-tavily-api-key" )
bound_llm = llm.bind_tools([tavily_tool])
structured_llm = bound_llm.with_structured_output(WeatherResult)
result = structured_llm.invoke("2026 年 3 月 2 日北京天气情况" )
print (f"地点:{result.location} " )
print (f"天气:{result.weather} " )
关键优势: 智能决策,精准执行,结果规范,流程清晰。
总结与建议 场景 核心价值 主要用途 信息提取器 非结构化 → 结构化 数据提取与转换 提示词增强 模糊意图 → 明确指令 意图理解与澄清 Tool 联合使用 智能决策 + 精准执行 复杂任务自动化
需要类型灵活切换 → 使用可选结构化输出。
固定的数据提取 → 使用单一 Pydantic 模型。
复杂嵌套结构 → 使用 JSON Schema 或嵌套 Pydantic 模型。
简单键值对 → 使用 TypedDict。
四种结构化输出方式各有优劣,Pydantic 在类型安全和 IDE 支持上表现最佳,TypedDict 轻量但类型检查弱,JSON Schema 标准化但定义繁琐。根据具体业务场景选择合适的方案即可。
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
随机西班牙地址生成器 随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online