news 2026/10/15 15:23:46

Langchain简单快速上手教程(四)—— 聊天模型之结构化输出

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Langchain简单快速上手教程(四)—— 聊天模型之结构化输出

前言

本期我将要介绍LangChain 中聊天模型的另一功能结构化输出。这将原来大模型输出的AIMessage变成以例如Json等格式化输出,以适应特定的开发场景。

一、with_structured_output() 方法

要想使用结构化输出能力,LangChain提供了一种方法.with_structured_output() 。该方法需要先定义输出结构,然后执行通过 .with_structured_output() 得到Runnable 实例。

(一)返回 Pydantic 对象

我们可以设置执行Runnable 后的输出结果指定为 Pydantic 类,这将返回一个 Pydantic 对象。当收到模型的响应后,LangChain 会提取出代表 Pydantic 参数的 JSON 对象,并用 Pydantic 模型对其进行解析和验证,将这个验证后的 JSON 转换为⼀个可用的 Pydantic 对象实例返回。

# 结构化返回 Pydantic model = ChatDeepSeek(model='deepseek-v4-flash') class Joke(BaseModel): """给用户讲的一个笑话""" setup:str = Field(description="笑话的开头") punchline: str = Field(description='笑话的妙语') rating: Optional[int] = Field(default=None,description="从1-10分,给这个笑话评分") class Data(BaseModel): """获取关于笑话的数据列表""" jokes: List[Joke] # print(model.invoke("讲一个关于薛定谔的猫的笑话").content) model_with_structured = model.with_structured_output(Data) print(model_with_structured.invoke("讲一个关于薛定谔的猫的笑话"))

(二)返回 TypedDict

TypedDict 主要用于为字典对象提供精确的、结构化的类型提示。它允许我们指定字典中应该有哪些键,以及每个键对应的值的类型。它其中一个重要的能力就是捕捉键名拼写错误与类型错误。

因此我们也可以设置执行Runnable 后的输出结果指定为 TypedDict 类,这将就会返回一个字典,且输出后,会根据设定进行验证。

model = ChatDeepSeek(model='deepseek-v4-flash') # 结构化返回 TypedDict class Joke(TypedDict): """给用户讲的一个笑话""" setup:str = Field(description="笑话的开头") punchline: str = Field(description='笑话的妙语') rating: Optional[int] = Field(description="从1-10分,给这个笑话评分") model_with_structured = model.with_structured_output(Joke,include_raw=True) print(model_with_structured.invoke("讲一个关于薛定谔的猫的笑话"))

(三)返回 JSON

为了声明 JSON,我们同时需要定义 JSON Schema。

model = ChatDeepSeek(model='deepseek-v4-flash') # 结构化返回 JSON Schema json_schema = { "title": "joke", "description": "给用户讲一个笑话。", "type": "object", "properties": { "setup": { "type": "string", "description": "这个笑话的开头", }, "punchline": { "type": "string", "description": "这个笑话的妙语", }, "rating": { "type": "integer", "description": "从1到10分,给这个笑话评分", "default": None, }, }, "required": ["setup", "punchline"], } model_with_structured = model.with_structured_output(json_schema) print(model_with_structured.invoke("讲一个关于薛定谔的猫的笑话"))

(四)选择输出格式

创建具有联合类型属性的父模式。

model = ChatDeepSeek(model='deepseek-v4-flash') class Joke(BaseModel): """给用户讲的一个笑话""" setup: str = Field(description="这个笑话的开头") punchline: str = Field(description="这个笑话的妙语") rating: Optional[int] = Field(default=None, description="从1-10分,给这个笑话评分") class Response(BaseModel): """以对话的方式回应""" content: str = Field(description="用于对用户查询的会话响应") class FinalResponse(BaseModel): """最终回复,选择合适的输出结构""" final_output: Union[Joke, Response] model_with_structured = model.with_structured_output(FinalResponse) print(model_with_structured.invoke("讲一个关于薛定谔的猫的笑话")) print(model_with_structured.invoke("你是谁?"))

二、实用案例

(一)信息提取

model = ChatDeepSeek(model='deepseek-v4-flash') # 结构化输出常见使用场景:信息提取 class Person(BaseModel): """一个人的信息。""" # 注意: # 1. 每个字段都是 Optional “可选的” —— 允许 LLM 在不知道答案时输出 None。 # 2. 每个字段都有一个 description “描述” —— LLM使用这个描述。 # 有一个好的描述可以帮助提高提取结果。 name: Optional[str] = Field(default=None, description="这个人的名字") hair_color: Optional[str] = Field(default=None, description="如果知道这个人头发的颜色") skin_color: Optional[str] = Field(default=None, description="如果知道这个人的肤色") height_in_meters: Optional[str] = Field(default=None, description="以米为单位的高度") structured_model = model.with_structured_output(schema=Person) messages = [ SystemMessage(content="你是一个提取信息的专家,只从文本中提取相关信息。如果您不知道要提取的属性的值,属性值返回null"), HumanMessage(content="史密斯身高6英尺,金发。") ] result = structured_model.invoke(messages) print(result)

(二)与工具结合使用

model = ChatOpenAI( model='deepseek-v4-flash', api_key=os.environ.get('DEEPSEEK_API_KEY'), base_url="https://api.deepseek.com", ) # 结构化输出常见使用场景:与工具结合使用 tool = TavilySearch(max_results=4) model_with_tools = model.bind_tools([tool]) messages = [ HumanMessage("北京今天的天气怎么样?") ] ai_message = model_with_tools.invoke(messages) messages.append(ai_message) for tool_call in ai_message.tool_calls: tool_message = tool.invoke(tool_call) messages.append(tool_message) class SearchResult(BaseModel): """结构化搜索对象""" query: str = Field(description="搜索查询") findings: str = Field(description="查询结果摘要") model_with_structured = model_with_tools.with_structured_output(SearchResult) print(model_with_structured.invoke(messages))

与工具相结合的方式下,它并不能直接帮我们输出想要的SearchResult搜索结果,而是只返回了AIMessage。所以with_structured_output 方法只是让模型知道有哪些工具可以调用,但是并不会自动执行工具。要获得工具执行后的结果并整合到最终的结构化输出中,我们需要手动执行。

结语

以上便是Langchain中如何使用聊天模型的格式化输出的内容了。如果喜欢我的内容,请点赞、收藏加关注,多多支持我,以及欢迎各位在评论区讨论交流,并指出我的不足,谢谢大家。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 15:23:09

STM32Cube-FW-F4 V1.28.0固件包详解:HAL库、CubeMX与工程实践

简介:意法半导体官方推出的STM32Cube-FW-F4-V1.28.0资源包,面向单片机与嵌入式开发工程师,为基于ARM Cortex-M4内核的STM32F4系列微控制器提供一套完整的软件开发基础。资源以zip压缩包形式发布,体积约611.5MB,文件总数…

作者头像 李华
网站建设 2026/10/15 15:22:40

Spring Boot+Vue前后端分离整合Shiro与JWT无状态认证实践

最近在给一个内部管理系统做前后端分离改造,后端是 Spring Boot,前端是 Vue 全家桶。原系统的权限体系用了很多年的 Shiro,所以第一反应是“不就是把 session 换成 token 嘛”,结果真动手之后才发现,Shiro 这套老框架默…

作者头像 李华
网站建设 2026/10/15 15:22:08

Simscape机械臂建模与仿真:从刚体搭建到PID控制实战

简介:面向机械臂建模初学者与Simscape仿真开发者,这份压缩包提供了一个三自由度(DOF)机械手臂从物理建模到动力学仿真的完整案例。模型源自roboholicmaniacs,采用步进电机作为执行器,以三个关节的扭矩角作为…

作者头像 李华
网站建设 2026/10/15 15:22:02

碰碰好评卡功能模块开发实战指南 附全流程实现思路与踩坑汇总

碰碰好评卡功能模块开发实战指南 附全流程实现思路与踩坑汇总 在电商、本地生活、上门服务等各类线上业务场景中,用户评价是影响商品/服务转化的核心指标,碰碰好评卡作为引导用户主动完成评价的核心功能模块,需要兼顾触发灵活性、多端兼容性、…

作者头像 李华
网站建设 2026/10/15 15:22:01

Grad-CAM原理解析与工业级实现指南

1. 这不是“画个热力图”那么简单:Grad-CAM到底在解决什么问题?Grad-CAM可视化,这五个字最近在模型可解释性讨论里出现频率极高,但很多人一上手就卡在“为什么我的热力图全是噪点”“为什么关键区域没亮起来”“为什么不同层的图完…

作者头像 李华