跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

LangChain 实战:工具调用与结构化输出应用指南

综述由AI生成深入探讨了 LangChain 中的工具调用与结构化输出技术。通过实战代码演示了三种工具创建方式及本地/第三方工具集成流程,详细对比了 Pydantic、TypedDict 和 JSON Schema 三种结构化输出方案的优劣。文章结合简历解析、意图识别及智能助手等场景,展示了如何将非结构化文本转化为规范数据,以及如何实现 AI 的智能决策与精准执行。核心在于利用结构化能力提升 AI 在自动化任务中的可靠性与可维护性。

人间过客发布于 2026/4/8更新于 2026/6/1119 浏览
LangChain 实战:工具调用与结构化输出应用指南

LangChain 实战:工具调用与结构化输出

工具调用(Tool Calling)和结构化输出是 LangChain 让 AI 从'聊天'走向'干活'的关键能力。前者允许模型调用外部函数或 API,后者则确保返回数据符合特定格式,便于程序处理。

工具调用(Tool Calling)

当 LLM 无法直接获取实时信息(如天气、数据库内容)时,我们可以借助工具完成查询。

创建工具的三种方式

  1. 直接用 @tool 装饰函数 最简单,适合轻量级小工具。
    from langchain_core.tools import tool
    
    @tool
    

def add(a: int, b: int) -> int: """计算两个数的和""" return a + b


2. **用 `@tool` + 自定义参数结构(Pydantic)**
参数更清晰,能写详细说明。
```python
from pydantic import BaseModel, Field

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
  1. 继承 BaseTool 写类 最灵活,适合复杂逻辑或异步操作。
    from langchain_core.tools import BaseTool
    
    class AddTool(BaseTool):
        name = "add_tool"
        description = "用于加法运算的工具"
    
        def _run(self, a: int, b: int) -> int:
             a + b
    
return

本地自定义工具实战

定义好工具后,需要将其绑定到模型。这里以 DeepSeek 模型为例。

from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage, SystemMessage, ToolMessage

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([add])

调用流程解析:

  1. 构建用户消息,包含系统提示和具体请求。
  2. 模型决定是否调用工具。如果决定调用,响应中会包含 tool_calls。
  3. 执行工具,并将结果包装为 ToolMessage 返回给模型。
  4. 模型根据工具结果生成最终回答。
message = [
    SystemMessage(content="你是一个数学助手。当用户给你一个数字 n 时,使用 add 工具计算结果。"),
    HumanMessage(content="请计算 5 加 3 的结果。"),
]

ai_message = bound_llm.invoke(message)
message.append(ai_message)

# 如果有工具调用,执行它
if ai_message.tool_calls:
    for tool_call in ai_message.tool_calls:
        if tool_call["name"] == "add":
            result = add.invoke(tool_call["args"])
            message.append(ToolMessage(content=str(result), tool_call_id=tool_call["id"]))

final_msg = bound_llm.invoke(message).content
print(final_msg)

注意: ai_message 是经过框架整合的响应,必须使用 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])

支持多轮调用,模型可以根据搜索结果自动判断是否需要进一步搜索。

结构化输出(Structured Output)

结构化输出允许模型返回符合特定格式的数据,而不是纯文本。这对于数据存储、API 响应生成等场景非常有用。

Pydantic BaseModel(推荐)

这是最常用且类型安全的方式。

from pydantic import BaseModel, Field

class WeatherInfo(BaseModel):
    city: str = Field(description="城市名称")
    weather: str = Field(description="天气状况")
    temperature: str = Field(description="温度范围")

model = llm.with_structured_output(WeatherInfo)
result = model.invoke("上海现在的天气如何?")
print(f"城市:{result.city}")

优点: 类型安全,IDE 有完整提示,支持字段验证。

TypedDict

轻量级方案,返回纯字典。

from typing import TypedDict, Annotated

class WeatherDict(TypedDict):
    city: Annotated[str, "城市名称"]
    weather: Annotated[str, "天气状况"]

model = llm.with_structured_output(WeatherDict)
result = model.invoke("北京天气")
print(result["city"])

缺点: 类型检查较弱,不支持 Field() 的高级功能。

JSON Schema

标准化格式,跨语言通用,适合复杂嵌套结构。

import json

json_schema = {
    "type": "object",
    "properties": {
        "city": {"type": "string", "description": "城市名称"},
        "weather": {"type": "string", "description": "天气状况"}
    },
    "required": ["city", "weather"]
}

model = llm.with_structured_output(json_schema)
result = model.invoke("广州天气")
print(json.dumps(result, ensure_ascii=False, indent=2))

可选结构化输出(动态类型选择)

当需要根据输入自动选择返回不同类型的数据时,可以使用 Literal 类型配合嵌套模型。

from typing import Literal

class PersonInfo(BaseModel):
    name: str
    age: int

class CityInfo(BaseModel):
    city: str
    population: int

class Response(BaseModel):
    type: Literal["person", "city"] = Field(description="响应类型")
    person: PersonInfo | None = None
    city: CityInfo | None = None

model = llm.with_structured_output(Response)
result = model.invoke("介绍一下张三")
if result.type == "person":
    print(f"姓名:{result.person.name}")

三大实际应用场景

1. 信息提取器

将非结构化文本转化为结构化数据。例如从简历中提取姓名、教育经历和工作经历。

from pydantic import BaseModel, Field

class Education(BaseModel):
    school: str
    degree: str

class ResumeInfo(BaseModel):
    name: str
    education: list[Education]

model = llm.with_structured_output(ResumeInfo)
resume_text = "...简历内容..."
result = model.invoke(f"提取信息:\n{resume_text}")

2. 提示词增强

帮助 AI 更好理解用户意图。将模糊需求转换为明确的结构化指令。

class SearchIntent(BaseModel):
    intent_type: Literal["informational", "transactional"]
    keywords: list[str]

intent = model.invoke("我想买个性价比高的笔记本")
# 根据 intent.intent_type 执行不同策略

3. 与 Tool 联合使用

结构化输出 + 工具调用的完美组合。AI 先分析需求并输出结构化决策,然后调用相应工具执行。

# 步骤 1:绑定工具
bound_llm = llm.bind_tools([tavily_tool])
# 步骤 2:绑定结构化输出
structured_llm = bound_llm.with_structured_output(WeatherResult)
# 步骤 3:直接调用
result = structured_llm.invoke("北京天气")

总结

方式优点适用场景
Pydantic类型安全、验证强复杂数据结构
TypedDict轻量、纯字典简单键值对
JSON Schema标准化、跨语言跨系统对接
可选输出灵活性高多类型动态响应

选择合适的输出方式取决于你的业务需求。如果是内部 Python 项目,Pydantic 通常是首选;如果需要与其他语言交互,JSON Schema 更稳妥。

目录

  1. LangChain 实战:工具调用与结构化输出
  2. 工具调用(Tool Calling)
  3. 创建工具的三种方式
  4. 本地自定义工具实战
  5. 绑定工具
  6. 如果有工具调用,执行它
  7. 第三方工具集成
  8. 结构化输出(Structured Output)
  9. Pydantic BaseModel(推荐)
  10. TypedDict
  11. JSON Schema
  12. 可选结构化输出(动态类型选择)
  13. 三大实际应用场景
  14. 1. 信息提取器
  15. 2. 提示词增强
  16. 根据 intent.intent_type 执行不同策略
  17. 3. 与 Tool 联合使用
  18. 步骤 1:绑定工具
  19. 步骤 2:绑定结构化输出
  20. 步骤 3:直接调用
  21. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • ROS2 在 RViz 中可视化 URDF 机器人模型
  • 大模型工具函数调用(Function Calling)实战指南
  • Stable Diffusion 本地运行硬件配置选择与优化指南
  • C++ 进阶:STL 红黑树实现与原理分析
  • 二分查找算法模板详解:核心原理与边界查找
  • C++ 内存区域详解:堆、栈与静态区变量存储
  • GESP 2023 年 12 月 C++ 二级认证试题解析(选择题 9-15)
  • Linux Ext 系列文件系统(一):文件系统的初识
  • 基于 MediaPipe Hands 的智能家居隔空操控实战
  • 大模型的终局是通用还是专用?
  • Python 字符串格式化、编码与深浅拷贝详解
  • GitHub Token 配置与安全使用指南
  • 前端 WebSocket 实战:替代轮询的实时通信方案
  • Ubuntu 24.04 安装 OpenClaw 时 systemctl is-enabled 报错解决
  • 滑动窗口算法解析:串联所有单词的子串与最小覆盖子串
  • QGroundControl 跨平台安装指南:Windows/macOS/Linux/Android
  • C++ Qt 网络编程:QUdpSocket、QTcpSocket 与 Http
  • Windows 下配置 WSL2 复现 Linux 项目:安装、报错修复与环境初始化
  • Spring Boot RESTful API 开发与测试
  • Java 经典排序算法全解析

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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