news 2026/9/15 19:43:01

使用 Instructor 与 Writer 实现结构化输出:Palmyra 模型完整接入指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 Instructor 与 Writer 实现结构化输出:Palmyra 模型完整接入指南

使用 Instructor 与 Writer 实现结构化输出:Palmyra 模型完整接入指南

【免费下载链接】instructorstructured outputs for llms项目地址: https://gitcode.com/GitHub_Trending/in/instructor

本指南聚焦于当前开源项目 instructor 对 Writer 平台的集成方案,完整演示如何通过instructor.from_provider("writer/palmyra-x5")一行代码获得 Writer 的结构化输出能力,覆盖同步/异步调用、嵌套对象抽取与流式输出三大实战场景,并深入底层源码揭示其工具调用(TOOLS)、JSON Schema 与 Markdown JSON(MD_JSON)三种工作模式的实现原理,帮助读者在真实业务中稳定地让 LLM 返回符合 Pydantic 模型约束的数据。

准备工作:账号、API Key 与安装

使用 Writer 结构化输出前,需要先完成两项准备:

  1. 注册 Writer 账号并获取 API Key:前往 Writer 官网注册账户,创建 API Key 后通过环境变量注入:
export WRITER_API_KEY=<your-api-key-here>
  1. 安装 instructor 的 Writer 扩展:项目通过可选依赖的方式提供 Writer 支持,安装命令如下:
pip install "instructor[writer]"

安装后,instructor 会在运行时按需导入 Writer 官方 SDK(writerai)。从 v2 Writer 客户端工厂源码 可以看到,SDK 采用惰性导入策略——只有当writerai真正被使用时才导入;如果未安装,from_writer会抛出ClientError,并提示你执行pip install writer-sdk。这保证了 instructor 核心包不会因为缺少某个厂商 SDK 而无法导入。

Palmyra-X 模型:自带工具调用能力

Writer 的 Palmyra-X 系列模型原生支持工具调用(tool calling)功能,这意味着可以将 Pydantic 模型直接转换为函数 schema 交给模型填充,从而获得稳定、符合结构约束的输出。在 instructor 的 provider 规格定义中,Writer 的默认模型标识为writer/palmyra-x5,并注册了writer别名(见 provider_specs.py),因此可以直接用from_provider("writer/palmyra-x5")快速初始化客户端。

说明:原版指南在描述中提及的模型为 Palmyra-X-004,而当前仓库源码中注册的默认模型字符串为writer/palmyra-x5,实际使用时以源码中确认可用的writer/palmyra-x5为准。

快速上手:同步结构化抽取

最基础的用法是定义一个 PydanticBaseModel,把抽取任务交给client.create

import instructor from pydantic import BaseModel # 初始化 Writer 客户端 client = instructor.from_provider("writer/palmyra-x5") class User(BaseModel): name: str age: int # 抽取结构化数据 user = client.create( messages=[{"role": "user", "content": "Extract: John is 30 years old"}], response_model=User, ) print(user) #> name='John' age=30

instructor 会自动完成「Pydantic 模型 → 工具 schema → 模型工具调用 → JSON 解析 → Pydantic 校验」的完整链路,返回给你的是已经通过类型校验的User实例,而不是一串需要手工解析的文本。

异步调用:async 版本

在高并发、IO 密集的场景下,可以使用异步客户端。只需要在from_provider中传入async_client=True

import instructor from pydantic import BaseModel import asyncio client = instructor.from_provider( "writer/palmyra-x5", async_client=True, ) class User(BaseModel): name: str age: int async def extract_user(): # 抽取结构化数据 user = await client.create( messages=[{"role": "user", "content": "Extract: John is 30 years old"}], response_model=User, ) print(user) #> name='John' age=30 if __name__ == "__main__": import asyncio asyncio.run(extract_user())

从底层实现看,from_writer工厂会根据传入客户端的类型自动分派:writerai.Writer(同步)返回Instructorwriterai.AsyncWriter(异步)返回AsyncInstructor,两者的创建函数都统一取自client.chat.chat(见 client.py)——这是 Writer SDK 与 OpenAI 风格 API 的一个关键差异点:Writer 使用chat.chat而非chat.completions.create

嵌套对象:复杂结构的抽取

真实业务中的实体往往包含层级关系。Writer 同样支持嵌套对象,instructor 会自动将嵌套的 Pydantic 模型展开为完整的 JSON Schema 交给模型:

import instructor from pydantic import BaseModel # 初始化 Writer 客户端 client = instructor.from_provider("writer/palmyra-x5") class Address(BaseModel): street: str city: str country: str class User(BaseModel): name: str age: int addresses: list[Address] # 创建带嵌套对象的结构化输出 user = client.create( messages=[ { "role": "user", "content": """ Extract: Jason is 25 years old. He lives at 123 Main St, New York, USA and has a summer house at 456 Beach Rd, Miami, USA """, }, ], response_model=User, ) print(user) #> { #> 'name': 'Jason', #> 'age': 25, #> 'addresses': [ #> { #> 'street': '123 Main St', #> 'city': 'New York', #> 'country': 'USA' #> }, #> { #> 'street': '456 Beach Rd', #> 'city': 'Miami', #> 'country': 'USA' #> } #> ] #> }

这里list[Address]类型的字段会被转换为数组形式的 JSON Schema,模型返回的多个地址将被逐一校验并组装为Address对象列表,适合从一段自由文本中同时抽取多个同类实体。

流式输出:两类场景

当输出内容较长或希望尽早开始处理结果时,instructor 提供两种流式方案,Writer 均已通过原生工具调用方式支持:

  1. Iterables(列表流):用于流式返回同一类型的多个对象,例如一次抽取多个用户;
  2. Partial Streaming(部分流):用于流式返回单个对象,在响应逐步到达时立即开始处理。

部分流式(Partial Streaming)示例

import instructor from pydantic import BaseModel client = instructor.from_provider("writer/palmyra-x5") class Person(BaseModel): name: str age: int resp = client.create_partial( messages=[ { "role": "user", "content": "Ivan is 27 and lives in Singapore", } ], response_model=Person, ) for person in resp: print(person) #> name=None age=None #> name='Ivan' age=None #> name='Ivan' age=27

可以看到,随着模型逐步生成 token,Person对象的字段会从None逐渐被填充,这正是部分流式输出的典型特征——下游可以在完整响应到达前就对已确定字段(如name)提前处理。

三种工作模式与底层实现

从源码看,Writer 集成在 v2 模式注册表中注册了三种 handler(见 handlers.py),这也是Mode枚举中WRITER_TOOLS/WRITER_JSON归一化后对应的能力集(映射关系见 mode.py):

模式Handler 类请求构造方式响应解析方式
TOOLS(默认)WriterToolsHandlerresponse_model通过generate_openai_schema转为 function schema,设置tools=[{"type": "function", "function": schema}]tool_choice="auto"读取choices[0].message.tool_calls[0].function.arguments,用model_validate_json校验
JSON_SCHEMAWriterJSONSchemaHandler设置response_format={"type": "json_schema", "json_schema": {"schema": model_json_schema()}},走 Writer 原生 JSON Schema 通道直接解析choices[0].message.content文本为 JSON
MD_JSONWriterMDJSONHandler将 schema 注入 system 消息,并要求模型在 ```json 代码块中返回 JSON通过extract_json_from_codeblock从代码块中提取 JSON 再校验

几点值得注意的实现细节:

  • 默认模式为TOOLSfrom_writermode参数默认取Mode.TOOLS,即优先利用 Palmyra 系列模型的原生工具调用能力(client.py);而WRITER_TOOLSWRITER_JSON这类厂商私有模式会在工厂内部被normalize_mode归一化为通用模式,保证与其他 provider 的行为一致。
  • reask 自动重试:当校验失败时,三种模式都注册了对应的 reask 处理函数(reask_writer_tools/reask_writer_json),会把上一次响应和校验错误信息拼回对话历史,要求模型修正输出,这正是 instructor 提高结构化输出成功率的机制之一。
  • 截断检测TOOLS模式解析响应时,如果检测到finish_reason == "length",会抛出IncompleteOutputException,避免静默返回不完整数据(见 handlers.py)。
  • mode 未注册时的保护:如果传入了 Writer 不支持的 mode,from_writer会抛出ModeError,并列出该 provider 实际可用的模式列表,便于排查。

仓库中的测试对以上行为做了直接验证(见 tests/v2/test_writer_handlers.py):例如断言 TOOLS 模式下tool_choice会被设置为"auto"、工具调用返回的 JSON 能正确解析为User(name="Alice", age=30)、MD_JSON 模式下嵌套 ```json 代码块能正确提取解析;此外 tests/v2/test_writer_client.py 还保证了三个 handler 均可正常导入。

兼容层说明

如果你在旧代码中看到from instructor.providers.writer import from_writer这样的导入路径,无需担心——instructor/providers/writer/ 下的__init__.pyclient.pyutils.py现在都是指向 v2 实现的兼容门面(facade),from_writer实际转发到instructor.v2.providers.writer.client.from_writer。因此无论走from_provider("writer/palmyra-x5")还是显式from_writer(writer_client),底层都是同一套 v2 注册表与 handler 体系。

小结

通过 instructor 接入 Writer 的结构化输出,核心路径只有三步:安装instructor[writer]→ 设置WRITER_API_KEYinstructor.from_provider("writer/palmyra-x5")。之后无论是同步、异步、嵌套对象还是流式输出,都可以用与 OpenAI 等其他 provider 完全一致的client.create/client.create_partial接口完成,Pydantic 模型的校验与自动重试则由底层WriterToolsHandler等模式处理器透明承接。若想深入源码,可从 v2 Writer 客户端工厂 与 v2 Writer 模式处理器 两个文件入手。

【免费下载链接】instructorstructured outputs for llms项目地址: https://gitcode.com/GitHub_Trending/in/instructor

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

湖南关键词优化排名推广实战:新手入门避坑指南

湖南关键词优化排名推广实战:新手入门避坑指南 网站做好了没人访问,这大概是所有独立站长最绝望的时刻。你花了几万块甚至几十万,找团队开发、买服务器、搞备案,结果上线一个月,百度指数查询,每天UV(独立访客)个位数,连自家亲戚点进来都不到三个。很多湖南的老板和新手在咨询湖南关键词优化排名推广时,第一反应…

作者头像 李华
网站建设 2026/9/15 19:37:34

AI如何通过智能写作工具提升学术论文效率

1. 项目概述&#xff1a;AI如何重塑学术写作体验在凌晨三点的大学图书馆里&#xff0c;面对堆积如山的文献资料和闪烁的光标&#xff0c;每个经历过毕业论文写作的人都能理解那种"学术写作困境"。传统写作工具往往只能提供基础的格式检查&#xff0c;而"书匠策A…

作者头像 李华
网站建设 2026/9/15 19:35:34

BLE蓝牙胎压监测方案:从选型到广播数据解析实战

1. 为什么我最终选择了 BLE 蓝牙胎压监测方案先交代一下背景。我这台车开了四年多&#xff0c;原车自带的是间接式胎压监测&#xff0c;也就是靠轮速差来判断轮胎是否漏气。这东西怎么说呢&#xff0c;不是不能用&#xff0c;但体验挺难受的——它只有在轮胎明显亏气、转速差足…

作者头像 李华
网站建设 2026/9/15 19:35:28

北航机器学习期末试卷考点全解析:从SVM到深度学习的复习指南

北航机器学习期末考试那份卷子&#xff0c;我是真真切切啃过一遍的。2020年春这份题&#xff0c;放在当年不算难&#xff0c;但覆盖面很扎实&#xff0c;从经典统计学习到深度学习的入门概念都有涉及。现在回头再看&#xff0c;这份试卷几乎就是北航《机器学习》这门课半学期的…

作者头像 李华