Instructor 结构化输出核心:用 Pydantic Response Model 定义 LLM 输出模式

发布时间:2026/9/15 11:22:22

Instructor 结构化输出核心:用 Pydantic Response Model 定义 LLM 输出模式 Instructor 结构化输出核心用 Pydantic Response Model 定义 LLM 输出模式【免费下载链接】instructorstructured outputs for llms项目地址: https://gitcode.com/GitHub_Trending/in/instructor本文以 Instructor 的 Models 概念文档 为核心骨架结合仓库源码instructor/v2/core/schema.py、instructor/v2/providers/openai/schema.py、instructor/v2/core/client.py与配套教程Response Models 教程、Fields 概念、Optional Fields 教程展开。读者将掌握如何用pydantic.BaseModel定义 LLM 输出结构、如何通过response_model让模型自动校验并返回类型化实例、如何利用 docstring 与字段注解进行提示词工程、如何处理可选字段、如何在运行时动态创建模型以及如何给模型挂载业务方法。什么是 Response ModelInstructor 的核心理念是用 Pydantic 模型定义你要什么让语言模型照着输出。在 Instructor 中这个用于描述输出结构的 Pydantic 模型就被称为Response Model。定义一个 Response Model 极其简单——它就是一个普通的pydantic.BaseModel子类from pydantic import BaseModel, Field class User(BaseModel): name: str Field(descriptionThe name of the user.) age: int Field(descriptionThe age of the user.)定义完成后把它作为response_model参数传给客户端例如client.create(...)Instructor 会在背后完成三件事定义 schema 与提示词把你的模型编译成 JSON Schema 并注入 prompt / 工具定义告诉语言模型应该输出什么形状的数据校验 API 返回对语言模型的原始输出进行解析与 Pydantic 校验类型不符或缺失字段都会触发重试详见 Retrying 概念返回模型实例最终交付的是一个已经通过校验的User实例而不是一坨需要手动解析的 JSON 字符串。对应到仓库源码响应处理的核心管线位于 instructor/v2/core/client.py其中create的签名里response_model: type[T]或None直接决定了本次调用是否走结构化输出分支而把模型变成发给 LLM 的 schema这一步在 v2 架构中按供应商拆分统一由 instructor/v2/core/schema.py 导出generate_openai_schema、generate_anthropic_schema、generate_gemini_schema三个兼容入口实际实现在各供应商目录下如 instructor/v2/providers/openai/schema.py。一个最小可用示例import instructor from pydantic import BaseModel, Field class User(BaseModel): name: str Field(descriptionThe name of the user.) age: int Field(descriptionThe age of the user.) client instructor.from_provider(openai/gpt-4o-mini) user client.create( response_modelUser, messages[{role: user, content: Extract: John is 30 years old}], ) print(user.name) # John print(user.age) # 30from_provider(openai/gpt-4o-mini)是 Instructor 提供的统一客户端创建接口支持 OpenAI、Anthropic、Gemini、Mistral、Cohere、Groq 等大量供应商完整列表见 Integrations 索引 与 from_provider 概念。用 docstring 与字段注解驱动提示词Response Model 不仅定义结构它本身还承载着提示词工程。Instructor 约定类的 docstring 就是发给语言模型的指令每个字段的类型注解与Field(description...)就是对该字段的说明。from pydantic import BaseModel, Field import instructor class User(BaseModel): This is the prompt that will be used to generate the response. Any instructions here will be passed to the language model. name: str Field(descriptionThe name of the user.) age: int Field(descriptionThe age of the user.) client instructor.from_provider(openai/gpt-4o-mini) user client.create( response_modelUser, messages[{role: user, content: Extract: John is 30 years old}], )源码层面的证据在 instructor/v2/providers/openai/schema.pygenerate_openai_schema用docstring_parser.parse(model.__doc__)解析类 docstring把其中的参数说明:param xxx: ...补进 JSON Schema 对应字段的description若整个模型没有 description则自动生成Correctly extracted \{model.name} with all the required parameters with correct types 作为工具描述。也就是说你写下的 docstring 与字段描述会被直接编译进发给 LLM 的 tool/function schema这就是用 Python 类型系统做提示词工程的原理。此外Pydantic 的Field还提供了更多可用于提示词工程的元数据详见 Fields 概念description字段语义说明title字段标题examples字段示例值可显著提升抽取准确性json_schema_extra向 JSON Schema 追加任意额外属性。这些都会进入model.model_json_schema()生成的 schema进而影响 LLM 的输出质量。让字段可选Optional 与默认值现实中的抽取任务经常遇到原文里没有这个信息的情况。此时可以把字段声明为Optional并给出默认值from pydantic import BaseModel, Field from typing import Optional import instructor class User(BaseModel): name: str Field(descriptionThe name of the user.) age: int Field(descriptionThe age of the user.) email: Optional[str] Field(descriptionThe email of the user., defaultNone) client instructor.from_provider(openai/gpt-4o-mini) user client.create( response_modelUser, messages[{role: user, content: Extract: John is 30 years old}], ) # user.email None需要注意两个关键点Optional[str]本身不产生默认值即使类型写成Optional[str]字段依然会被视为必填required。必须显式给出defaultNone或default_factory字段才会在发给 LLM 的 schema 中标记为可选。这一点在 Fields 概念 中也有明确提示。JSON Schema 层面可选字段意味着该字段允许为null同时Optional不改变类型的描述LLM 在信息缺失时倾向于返回null而不是凭空编造。关于可选值还有两套进阶工具Maybe[T]类型用于表达模型也不确定的字段返回值包裹在Maybe容器中可通过is_uncertain判断置信度详见 Maybe 概念 与 Optional Fields 教程SkipJsonSchema注解如果某个字段例如private_field、scratch_pad不想让语言模型看到可以用 Pydantic 的SkipJsonSchema[...]把它从发给 LLM 的 schema 中剔除并配合默认值使用见 Fields 概念中的对应小节。从源码看可选字段不进入 required 集合的行为是有意为之在 instructor/v2/providers/openai/schema.py 的注释中明确说明parameters[required]直接复用 Pydantic 自己计算出的schema.get(required, [])而 Pydantic 的 required 集合天然排除了带默认值无论是default还是default_factory的字段——这也解释了为什么只写Optional而不给默认值不生效。运行时动态创建模型当输出结构在编码期无法预知例如由数据库配置、用户配置或动态业务规则决定时可以使用 Pydantic 的create_model在运行时构造模型。基础用法from pydantic import BaseModel, create_model class FooModel(BaseModel): foo: str bar: int 123 BarModel create_model( BarModel, apple(str, russet), banana(str, yellow), __base__FooModel, ) print(BarModel) # class __main__.BarModel print(BarModel.model_fields.keys()) # dict_keys([foo, bar, apple, banana])create_model的字段参数形式为(类型, 默认值或 Field)同时可以用__base__继承已有模型实现字段的合并与复用。典型场景从数据库配置构建模型文档给出的典型场景是模型的结构保存在数据库中例如一张prompt表存有每个model_name对应的property_name / property_type / descriptionSELECT property_name, property_type, description FROM prompt WHERE model_name {model_name}拿到查询结果后用create_model一行代码完成模型构建from pydantic import BaseModel, create_model, Field from typing import List types { string: str, integer: int, boolean: bool, number: float, List[str]: List[str], } # Mocked cursor.fetchall() cursor [ (name, string, The name of the user.), (age, integer, The age of the user.), (email, string, The email of the user.), ] BarModel create_model( User, **{ property_name: (types[property_type], Field(descriptiondescription)) for property_name, property_type, description in cursor }, __base__BaseModel, ) print(BarModel.model_json_schema())输出正是标准 JSON Schema可作为response_model直接使用{ properties: { name: {description: The name of the user., title: Name, type: string}, age: {description: The age of the user., title: Age, type: integer}, email: {description: The email of the user., title: Email, type: string} }, required: [name, age, email], title: User, type: object }这套模式的价值在于同一个代码库可以为不同用户/场景生成字段相同、描述不同的模型——字段描述即提示词因此等于实现了同一结构、个性化 prompt。关于 JSON Schema 生成的更多细节Optional 允许 null、Decimal 序列化为字符串、子模型进入$defs等见 Fields 概念文档的附录。给模型添加行为让抽取结果会做事Pydantic 模型本质是 Python 类因此可以像普通类一样定义方法为抽取结果附加业务逻辑from pydantic import BaseModel from typing import Literal import instructor client instructor.from_provider(openai/gpt-4.1-mini) class SearchQuery(BaseModel): query: str query_type: Literal[web, image, video] def execute(self): print(fSearching for {self.query} of type {self.query_type}) # Searching for cat of type image return Results for cat query client.create( modelgpt-4.1-mini, messages[{role: user, content: Search for a picture of a cat}], response_modelSearchQuery, ) results query.execute() print(results) # Results for cat在这里Literal[web, image, video]让 LLM 的输出被约束到枚举取值内详见 Enums 概念而execute()方法则在抽取完成后原地执行后续动作。这种结构 行为一体的模式非常适合将 RAG 检索、SQL 执行、API 调用等副作用封装在模型内部——官方博客 RAG is more than embeddings 中有更多此模式的实际案例。类似地Pydantic 还支持用field_validator/model_validator挂载自定义校验逻辑使模型内部即可校验、失败则自动重试参考 Validation 概念 与 Custom Validators 教程。组合进阶从简单模型到复杂结构Response Model 的能力可以自由组合覆盖从简单到复杂的各类抽取需求详见 Response Models 教程嵌套模型addresses: List[Address]实现分层数据结构抽取列表字段tags: List[str]一次抽取多个同类条目字段校验price: float Field(gt0)、name: str Field(min_length3)让 Pydantic 在解析时完成边界校验文档即提示为模型写 docstring、为字段写 description让 LLM 与同事都能理解模型语义。一个综合示例结合 Simple Object Extraction 与 Nested Structure 教程from typing import List, Optional from pydantic import BaseModel, Field class Address(BaseModel): street: str city: str country: str class User(BaseModel): A user record extracted from unstructured text. name: str Field(descriptionFull name of the user.) age: Optional[int] Field(defaultNone, descriptionAge if mentioned.) addresses: List[Address] Field(descriptionAll known addresses.) # 作为 response_model 使用 # user client.create(response_modelUser, messages[...])常见问题与排查要点字段声明了Optional却仍被要求必填Optional不自动产生默认值请补上 None或default_factory。不想让 LLM 看到/生成某字段用SkipJsonSchema[...]从 schema 中剔除并给出默认值避免校验失败。抽取结果字段总是错误或缺失优先检查 docstring 与Field(description...)是否准确——它们直接编译进发给 LLM 的 schema源码见 instructor/v2/providers/openai/schema.py。结构在编码期未知用create_model从配置/数据库动态构建字段描述按需生成。希望失败自动重试Instructor 默认在响应校验失败时携带错误信息向 LLM 重试可参考 Retrying 概念 调整max_retries。参考与延伸阅读Response Models 教程创建响应模型的分步指南Simple Object Extraction基础抽取模式Nested Structures复杂层级模型Optional Fields可选数据的处理Types各类数据类型的使用Fields字段高级配置与 JSON Schema 定制Maybe 概念表达不确定的字段Fields 文档中的相关小节SkipJsonSchema用法【免费下载链接】instructorstructured outputs for llms项目地址: https://gitcode.com/GitHub_Trending/in/instructor创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/15 11:22:22

呼叫中心SIP中继对接实战:VOS与OKCC从路由配置到话单同步

接触呼叫中心业务的朋友都有体会,一套完整的外呼链路往往不是靠单个系统硬撑起来的。线路资源、语音网关、号码路由、并发控制这些东西,和坐席管理、客户资料、外呼任务、通话报表,天然属于两个不同的管理层次。如果硬要把它们塞在一个系统里…

2026/9/15 11:22:22

TypeScript接口重载实战:告别any,精确推导Web请求类型

做Web开发的人,尤其是用TypeScript写前端工程写了几年之后,多少都会遇到这样一个场景:同一个函数、同一个接口,入参不同,返回的类型也不同。用any吧,类型保护全丢了;用联合类型吧,每…

2026/9/15 11:37:24

leetcode滑动窗口问题

想成功先发疯,不顾一切向前冲。 第一种 定长滑动窗口 . - 力扣(LeetCode)1456.定长子串中的元音的最大数目. - 力扣(LeetCode) No.1 定长滑窗套路 我总结成三步:入-更新-出。 1. 入:下标为…

2026/9/15 11:37:24

建设一个网站选择的服务器别被坑:2026最新省钱实操指南

建设一个网站选择的服务器别被坑:2026最新省钱实操指南 找建站公司,最怕什么?怕对方张嘴就是“高配套餐”,把你当韭菜割。很多老板以为服务器越贵越好,结果一年下来服务器费用比开发费还高,网站还没跑起来,钱先烧光了。别急,2026年最新的市场…

2026/9/15 11:37:24

VeraCrypt 数据恢复:3 类典型故障的快速修复路径

VeraCrypt 数据恢复:3 类典型故障的快速修复路径 【免费下载链接】VeraCrypt Disk encryption with strong security based on TrueCrypt 项目地址: https://gitcode.com/GitHub_Trending/ve/VeraCrypt "无法挂载卷:卷头已损坏"&#x…

2026/9/15 11:32:22

卡尔曼滤波预测与关联:雷达点迹转航迹工程实践

简介:这是一份基于卡尔曼滤波实现目标点迹处理与航迹预测的Matlab仿真资源,适合雷达数据处理、目标跟踪初学者或需要快速验证卡尔曼滤波效果的开发者使用。资源围绕单目标航迹生成场景,将测量点迹作为输入,通过滤波递推自动形成连…

2026/9/15 4:54:30

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/15 0:01:16

AI英语单词APP开发:自适应学习算法与移动端优化实践

1. 项目概述 作为一名在移动应用开发领域摸爬滚打多年的老手,我最近完成了一个AI英语单词APP的开发项目。这个项目将传统单词记忆方法与现代AI技术相结合,打造了一款能够智能适应不同用户学习习惯的英语学习工具。 市面上大多数单词APP都存在一个通病&a…

2026/9/15 0:01:16

Flutter与OpenHarmony结合开发手语学习APP实战

1. 项目背景与核心价值作为一名同时接触过Flutter和OpenHarmony的开发者,最近我完成了一个基于Flutter for OpenHarmony的手语学习APP实战项目。这个项目最大的特点在于实现了跨平台框架与国产操作系统深度结合的创新实践——用Flutter开发的应用能完美运行在OpenHa…

2026/9/15 0:01:16

六个月成为机器人工程师:从ROS2到SLAM的实战路径

1. 六个月的紧迫感从哪来:先搞清楚你要成为哪种机器人工程师说实话,六个月的期限并不是一个宽松的时间线。市面上任何一本正经的机器人学教材都超过五百页,ROS2的官方文档可以翻到你怀疑人生,再加上ABB、KUKA这些工业机器人厂家动…

2026/9/14 11:59:31

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/14 13:53:59

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/14 11:22:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码