目录
一、聊天模型的绑定
绑定工具
bind_tools() 方法定义
工具调用
强制模型调用工具
工具属性
将工具输出传递给聊天模型
二、LangChain 提供的工具
TavilySearch
三、聊天模型 -- 结构化输出
with_structured_output()
with_structured_output() 方法定义
返回 Pydantic 对象
返回 TypedDict
返回 JSON
四、选择输出格式
五、实用场景
场景 1:作为信息提取器
场景 2:使用 “少样本提示” 来增强信息提取能力
场景 3:与工具结合使用
六、总结
一、聊天模型的绑定
上篇文章我们讲了聊天模型的定义、部署、创建与调用,下面我们接着来看聊天模型的绑定。
绑定工具
为了实际将这些工具绑定到聊天模型,可以使用聊天模型的.bind_tools()方法。
bind_tools() 方法定义
请求参数:
tools:绑定到此聊天模型的工具定义列表。支持的类型为:字典、pydantic.BaseModel 类、Python 函数和 BaseTool(如
@tool装饰器创建的类)。tool_choice(默认空):要求模型调用哪个工具。可以设置为:
- 形式为 <<tool_name>> 的 str:调用 <tool_name> 工具。
- 'auto':自动选择工具(包括无工具)。
- 'none':不调用工具。
- 'any' 或 'required' 或 True:强制调用至少一个工具。
- False 或 None:无效果,默认 OpenAI 的行为。
strict(默认空):
- 如果为 True,则保证模型输出与工具定义中提供的 JSON Schema 完全匹配。输入也将根据提供的 Schema 进行验证。
- 如果为 False,则不会验证输入,也不会验证模型输出。
- 如果为 None,则不会将 strict 参数传递给模型。
parallel_tool_calls:默认为 None,允许并行工具使用。设置为 False 以禁用并行工具。
kwargs(Any):任何附加参数都直接传递给 bind()。
返回值:
- 返回一个 Runnable 实例。
- 该实例支持多种格式输入:
- 原始提示 PromptValue
- 字符串:"上海天气如何?"
- 消息或消息列表:[HumanMessage(content="...")]
- 该实例的输出:
- 包含工具调用信息的 AIMessage
工具调用
通过 .bind_tools() 方法我们可知,它返回了一个 Runnable 实例,因此我们可以使用该 Runnable 实例,调用 .invoke() 方法,完成工具调用。示例如下:
输出结果(AIMessage):
输出说明:
- AIMessage:来自 AI 的消息。从聊天模型返回,作为对提示(输入)的响应。
- content:消息的内容。
- additional_kwargs:与消息关联的其他有效负载数据。对于来自 AI 的消息,可能包括模型提供程序编码的工具调用。
- response_metadata:响应元数据。例如:响应标头、logprobs、令牌计数、模型名称。
从输出结果看来,AI 给出的响应是进行工具的调用!
工具调用的一个关键原则是,模型根据输入的相关性决定何时使用工具。模型并不总是需要调用工具。例如,给定一个不相关的输入,模型不会调用该工具。
强制模型调用工具
当然我们也可以让模型强制调用工具,那就需要在绑定工具时,设置 tool_choice="any",表示强制调用至少一个工具。示例如下:
工具属性
现在我们知道,输出结果是一个 AIMessage。但是如果调用了工具,则 result 将具有一个 tool_calls 属性。此属性包括执行该工具所需的一切,包括工具名称和输入参数,示例如下:
输出结果:
将工具输出传递给聊天模型
到这里可以发现,我们仅仅只是成功调用了工具,但是聊天模型并没有给我们返回我们真正需要的答案。此时就需要:
- 将工具输出传递给聊天模型,包括
HumanMessage、AIMessage(工具调用)、ToolMessage。 - 聊天模型根据以上消息输入,将最终结果
AIMessage返回。
为什么要发 ToolMessage 呢?之前我们讲过,聊天模型通常不是接受单个字符串作为输入,而是接受聊天消息(xxxMessage)列表,因此在这里我们需要将工具的返回,构造成 ToolMessage,再传输给聊天模型!
方便的是,如果我们使用 @tool 装饰器创建的工具,使用 tool.invoke(tool_calls),将自动返回一个 ToolMessage。完整示例如下:
从流程与代码中可以看到,实际上我们调用了两次聊天模型:
- 第一次:仅将【HumanMessage】发送给聊天模型进行处理,结果返回了【包含工具调用的 AIMessage】,并没有返回我们想要的结果。然后我们执行工具,得到 ToolMes sage。
- 第二次:将【HumanMessage + AIMessage + ToolMessage】消息记录发送给聊天模型进行处理,结果返回了【包含结果的 AIMessage】。
二、LangChain 提供的工具
工具也不是全部都需要我们自己手搓,其实LangChain 官方也已经给我们提供了很多现成的工具 (Tool) 和工具包 (Toolkit)。写好的工具一般都是为了使用 LangChain 中集成的三方组件或工具而创造的,有搜索、数据库、网页浏览器等相关的工具。
LangChain 中的工具实际上是继承了 BaseTool 与 BaseToolkit。我们可以从下载的 LangChain 包的 Lib 中查看,全局搜索 BaseTool 和 BaseToolkit。
这里展示的全部是不同功能的现成的工具,我们可以直接使用它们!找到相关的类名称,去官网 API Reference 全局搜索,即可获取工具的详细说明与用法。
下面我们简单看一个搜索工具类。
TavilySearch
TavilySearch 类可以支持我们进行搜索,Tavily 是一个专门为 AI 设计的搜索引擎,专为智能体检索与推理需求量身打造的工具。
Tavily 不仅提供了高度可编程的 API 接口,还具备显著优于传统搜索引擎的上下文相关性理解能力。能够以结构化、可解析的形式返回搜索结果,便于将检索到的信息直接用于后续的推理、生成或任务执行流程。
Tavily 官网:Tavily,需魔法使用。登录完成后,新建 API Keys。
点击左侧 API Playground,可以使用刚申请的 API Keys,进行搜索测试。这会返回根据查询内容得到的多条搜索结果。
点击左侧 Use Cases,可以试用提供好的案例,如聊天中可以支持搜索(Chat)。
使用 Chat:
下面我们在 LangChain 中接入该搜索工具,步骤如下:
1. 安装 langchain‑tavily 包:
2. 配置环境变量 TAVILY_API_KEY,值为我们申请的 API Key。
3. 代码接入 TavilySearch 类,实现搜索功能:
结果打印:
三、聊天模型 -- 结构化输出
在 LangChain 中,聊天模型提供了额外的功能:结构化输出。一种使聊天模型以结构化格式(例如 JSON)进行响应的技术。例如,可能希望将模型输出存储在数据库中,并确保输出符合数据库模式。这种需求激发了结构化输出的概念,其中可以指示模型使用特定的输出结构进行响应。
核心原因:实现从 “字符串” 到 “对象” 的范式转换。 在没有该功能之前,调用聊天模型得到的是AIMessage,内容是普通字符串。伪代码示例:
字符串对人类友好,但对程序不友好。如果想要从中提取 “公司名” 和 “股价变化” 交给后续逻辑,需要手写复杂、容易出错的解析代码(正则表达式等)。
聊天模型的 with_structured_output 方法可以预先定义期望的数据结构,强制大模型按照该结构返回信息。
with_structured_output()
想要使用结构化输出能力,LangChain 提供.with_structured_output()方法。步骤伪代码:
这是获取结构化输出最简单、最可靠的方式。把输出结构作为参数传入,返回一个类似 model 的 Runnable。执行之后不再返回字符串 / 消息对象,而是和 schema 匹配的 Python 对象。
schema 支持传入TypedDict、JSON Schema、Pydantic类。
- TypedDict / JSON Schema:返回字典
- Pydantic 类:返回 Pydantic 实例对象
with_structured_output() 方法定义
请求参数:
- schema:输出结构。支持 JSON、TypedDict、Pydantic、OpenAI 函数 / 工具。
- method:LLM 生成方式
- json_schema(默认):使用 OpenAI 结构化输出 API
- function_calling:使用 OpenAI 工具调用(旧称函数调用)
- json_mode:OpenAI json 模式;注意:使用该模式需要自己在 prompt 里说明 schema 格式
- include_raw
- False(默认):只返回解析完成的结构化对象;解析出错直接抛异常
- True:返回原始消息 + 解析结果;返回字典包含raw、parsed、parsing_error三个 key,解析异常也会捕获返回
- strict
- True:强制模型输出严格匹配 schema,同时校验传入 schema
- False:不校验 schema,也不校验模型输出
- None(默认):不把 strict 参数传给模型
- tools:绑定工具列表,要求method="json_schema"、strict=True、include_raw=True,原始结果会放在 raw 字段
- kwargs:其余参数直接透传给 bind ()
返回值:
返回 Runnable 实例。
- include_raw=False
- schema 是 Pydantic 类:输出 Pydantic 对象
- 其他情况:输出字典
- include_raw=True,返回字典:
- raw:BaseMessage 原始消息
- parsed:解析后的对象,解析失败为 None
- parsing_error:解析异常对象,无异常则为空
返回 Pydantic 对象
我们可以设置执行 Runnable 后的输出结果指定为 Pydantic 类,这将返回一个 Pydantic 对象。
当收到模型的响应后,LangChain 会提取出代表 Pydantic 参数的 JSON 对象,并用 Pydantic 模型对其进行解析和验证,将这个验证后的 JSON 转换为一个可用的 Pydantic 对象实例返回。
如下所示:
打印结果:
还支持嵌套输出:
打印结果:
返回 TypedDict
先了解一下 TypedDict,它用于为字典对象提供精确的、结构化的类型提示。它允许我们指定一个字典中应该有哪些键,以及每个键对应的值的类型。
最清晰、最常用的定义方式,就是类似于定义一个类(Python3.8+),如下所示:
它重要的一个能力就是捕捉键名拼写错误与类型错误。
因此,我们也可以设置执行 Runnable 后的输出结果指定为 TypedDict 类,这将返回一个字典,且输出后,会根据设定进行验证。以下是该方法的使用姿势:
打印结果:
让我们加入include_raw=True,再来看看效果:
打印结果:
raw:原始大模型返回消息对象;parsed:解析完成的字典;parsing_error:解析异常,无异常为 None。
返回 JSON
还可以让聊天模型直接返回 JSON,只不过为了声明 JSON,我们需要定义 JSON Schema,如下所示:
打印结果:
三种 schema 小结:
- Pydantic BaseModel:返回 Pydantic 对象,
.属性访问,运行时自动校验,开发最常用。 - TypedDict:返回普通字典,
["key"]访问,仅静态类型提示,运行时不校验。 - JSON Schema:手写字典形式的 schema,返回普通字典,适合非 Python 环境对接、动态生成 schema 场景。
三者传给 with_structured_output() 都可以实现结构化输出,底层都会转为 OpenAI 识别的 json‑schema。
四、选择输出格式
创建具有联合类型属性的父模式,以使用 Pydantic 为例(其他同理),代码如下:
打印结果:
五、实用场景
场景 1:作为信息提取器
如下所示:
打印结果:
场景 2:使用 “少样本提示” 来增强信息提取能力
这里由于 [少样本提示] 能力我们还未讲解,这部分代码示例放在 [少样本提示] 部分讲解。
场景 3:与工具结合使用
注意,使用聊天模型原生的工具搭配结构化输出并不好用!!!这里只是了解下其能力。更好的用法见 LangGraph Agent 能力。
方式 1:使用with_structured_output()
输出结果:
可以看到,它并不能直接帮我们输出想要的 SearchResult 搜索结果,而是只返回了 AIMessage (工具调用信息)。
实际上,with_structured_output 方法只是让模型知道有哪些工具可以调用,但是并不会自动执行工具。要获得工具执行后的结果并整合到最终的结构化输出中,我们需要手动处理工具调用,然后将工具返回的结果再次传递给模型。见方式 2。
方式 2:拆解能力,单独依次执行
当需要同时使用结构化输出和其他工具时,需要注意顺序,不要弄反:
- 首先绑定工具
- 其次添加结构化输出
代码演示(版本 1):
打印结果:
改造版本完整代码:
打印结果:
这次的结果符合我们的预期。但依旧很麻烦,因为实际上调用了两次模型:
- 第一次调用模型:模型返回工具调用,我们手动执行工具,将工具结果加入消息列表。
- 第二次调用模型:传入完整消息列表(包含工具返回结果),输出结构化对象。
如果不想手动写两次调用、手动处理工具消息,后续学习LangGraph的 Agent 就可以自动化完成这个流程。
六、总结
本文介绍了 LangChain 聊天模型的绑定工具、结构化输出功能及实用场景。主要内容包括:1. 使用 .bind_tools() 方法将工具绑定到聊天模型,支持强制调用工具和并行工具调用;2. 通过 .with_structured_output() 实现结构化输出 (Pydantic对象/TypedDict/JSON),便于程序处理;3. 官方工具集 (如TavilySearch) 的使用方法;4. 结构化输出与工具调用的结合方式及注意事项;5. 典型应用场景如信息提取和少样本提示增强。文章强调结构化输出实现了从字符串到对象的范式转换,但指出原生工具与结构化输出的组合使用存在局限,建议后续结合 LangGraph Agent 实现自动化流程。