news 2026/9/15 18:25:24

Gemini 结构化输出实战:使用 Instructor 与 Google GenAI SDK 构建类型安全的数据提取

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Gemini 结构化输出实战:使用 Instructor 与 Google GenAI SDK 构建类型安全的数据提取

Gemini 结构化输出实战:使用 Instructor 与 Google GenAI SDK 构建类型安全的数据提取

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

本指南以 Instructor 的 Google 集成为主线,讲解如何基于 Google 官方推荐的google-genaiSDK,用from_provider("google/<model>")一行初始化客户端,通过 Pydantic 响应模型从 Gemini 模型中稳定提取结构化数据,并覆盖同步/异步、嵌套模型、generation_config参数调优、多模态图片输入、安全设置、流式输出与旧 SDK 迁移等完整场景。读完本文,你将掌握在 Instructor 中正确选用 Gemini 前缀与 Mode、配置生成参数、处理图片与安全阈值,以及规避 Union 类型等已知限制的实战能力。

前置准备:安装与 Provider 前缀选择

Google 的 GenAI SDK(google-genai)是访问 Gemini 模型的推荐方式,它为 Gemini API 与 Vertex AI 提供了统一接口。Instructor 通过instructor[google-genai]附加依赖安装:

pip install "instructor[google-genai]"

在 Instructor 中,同一个 SDK 存在三条前缀路径,选择前先明确差异(原文档明确建议):

前缀状态底层 SDK说明
google/<model>推荐google-genai(当前 SDK)面向 Gemini API;搭配vertexai=True可切换至 Vertex AI
vertexai/<model>已弃用请迁移到google/<model>+vertexai=True
gemini/<model>遗留google-generativeai(旧包)请迁移到google/<model>

从源码上看,from_provider在 instructor/v2/auto_client.py 中按provider/model-name格式解析前缀(约 L108-L115),并由 _build_google 负责 Google 分支的客户端构建。该分支会从kwargs中弹出vertexai标志(默认False),从GOOGLE_API_KEY环境变量读取密钥,并透传projectlocationcredentialshttp_options等客户端级参数,随后统一调用instructor.from_genai(client, mode=..., use_async=..., model=...)

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

定义一个 Pydantic 模型作为输出契约,用from_provider创建客户端,即可通过client.create完成提取:

import instructor from pydantic import BaseModel class User(BaseModel): name: str age: int # Using from_provider (recommended) client = instructor.from_provider( "google/gemini-3.8-flash", ) resp = client.create( response_model=User, messages=[ { "role": "user", "content": "Extract Jason is 25 years old.", } ], ) print(resp) # User(name='Jason', age=25)

其底层调用链清晰可循:from_genai(定义于 instructor/v2/providers/genai/client.py)将google.genai.Client包装为 Instructor 客户端,通过patch_v2注册对应模式的请求处理器;处理器负责把 OpenAI 风格的messages转换为 GenAI 的contents格式(见 handlers.py 中_convert_messages_to_contents),再调用client.models.generate_content完成请求。messages参数也可以是纯字符串或google.genai.types.Content对象,Instructor 均能兼容。

模型名按你所使用的 Gemini 实际命名传入即可,仓库其他文档与示例中常见的有google/gemini-2.5-flashgoogle/gemini-pro(参见 docs/integrations/genai.md 与 docs/concepts/from_provider.md)。

异步支持

Instructor 对 Google GenAI SDK 提供完整的异步支持。使用async_client=True创建异步客户端,配合await client.create(...)调用:

import instructor from pydantic import BaseModel import asyncio class User(BaseModel): name: str age: int async def extract_user(): client = instructor.from_provider( "google/gemini-3.8-flash", async_client=True, ) user = await client.create( messages=[ { "role": "user", "content": "Extract Jason is 25 years old.", } ], response_model=User, ) return user # Run async function user = asyncio.run(extract_user()) print(user) # User(name='Jason', age=25)

注意:使用异步客户端时,务必在调用它的同一事件循环内声明客户端。否则会触发大量事件循环相关的错误(如RuntimeError)。从源码可见,异步包装器通过client.aio.models.generate_content发起调用(client.py),异步客户端与事件循环绑定紧密。

配置选项:generation_config 参数详解

你可以通过generation_config字典定制模型行为,控制随机性、输出长度与采样方式。常用参数如下:

参数作用取值范围 / 说明
temperature控制输出随机性0.0~1.0,值越高越发散
max_tokens最大生成 token 数正整数,受模型上下文限制
top_pNucleus(核)采样参数0.0~1.0
top_k仅考虑概率最高的前 K 个 token正整数
import instructor from pydantic import BaseModel class User(BaseModel): name: str age: int client = instructor.from_provider( "google/gemini-3.8-flash", mode=instructor.Mode.JSON, ) resp = client.create( response_model=User, messages=[ { "role": "user", "content": "Extract Jason is 25 years old.", }, ], generation_config={ "temperature": 0.5, "max_tokens": 1000, "top_p": 1, "top_k": 32, }, ) print(resp)

从源码看,Instructor 会在 request.py 的update_genai_kwargs中将这些“OpenAI 风格”参数映射为 GenAI 的GenerateContentConfig字段,映射表如下,这意味着你无需学习两套命名:

  • max_tokensmax_output_tokens
  • temperaturetemperature
  • ncandidate_count
  • top_ptop_p
  • stopstop_sequences
  • seedseed
  • presence_penaltypresence_penalty
  • frequency_penaltyfrequency_penalty

此外,handlers.py_cleanup_provider_kwargs与两个 Handler 的prepare_request也会将散落在顶层kwargs中的max_tokenstemperaturetop_pseed等参数统一收拢进generation_config,再合并进config发送给 SDK。

值得注意的细节:当响应因max_tokens截断(finish_reason == MAX_TOKENS)而无法完整解析时,Instructor 会抛出IncompleteOutputException而非返回带有字段默认值的残缺对象(见 handlers.py)。这能避免“模型其实没生成某字段,却与模型主动选择的值无法区分”的坑。

多模态输入与图片安全设置

Gemini 是多模态模型,Instructor 通过统一的ImageAudioPDF对象封装媒体输入。以图片为例,可使用Image.autodetect(支持本地路径、HTTP URL、gs://地址与 base64,见 instructor/v2/core/multimodal.py),或显式的Image.from_url/Image.from_path/Image.from_base64

Google GenAI 对图片输入使用一套独立的危害类别(例如HARM_CATEGORY_IMAGE_HATE)。当请求包含图片内容时,Instructor 会自动处理:

  • 在请求配置中使用图片专属的类别;
  • 将你为文本类别(如HARM_CATEGORY_HATE_SPEECH)传入的阈值映射到对应的图片类别(如HARM_CATEGORY_IMAGE_HATE)。

这样可以避免同时传safety_settings与图片时出现400 INVALID_ARGUMENT错误。

import instructor from google.genai.types import HarmBlockThreshold, HarmCategory from instructor.processing.multimodal import Image from pydantic import BaseModel class Result(BaseModel): summary: str client = instructor.from_provider("google/gemini-3.8-flash") result = client.create( response_model=Result, messages=[ { "role": "user", "content": [ "Describe the image in one sentence.", Image.autodetect("path/to/image.png"), ], } ], # You can still pass text categories. Instructor will map them for image inputs. safety_settings={ HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE, }, ) print(result)

源码层面,request.pyupdate_genai_kwargssafety_settings的处理逻辑(L35-L65)会:默认将所有文本类别的阈值置为HarmBlockThreshold.OFF,再以用户传入的字典逐类别覆盖;图片请求时剔除HARM_CATEGORY_IMAGE_*前缀的类别,交由 GenAI SDK 的图片专用处理。底层媒体编码器位于 instructor/v2/providers/genai/multimodal.py,其中image_to_genaigs://、HTTP URL、base64 分别生成对应的Part.from_bytes

嵌套结构提取

结构化输出的价值在于可以提取任意复杂的嵌套对象。定义一个含列表嵌套字段的 Pydantic 模型,Gemini 会一次性返回完整的嵌套结构:

import instructor from pydantic import BaseModel class Address(BaseModel): street: str city: str country: str class User(BaseModel): name: str age: int addresses: list[Address] client = instructor.from_provider( "google/gemini-3.8-flash", ) 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' #> } #> ] #> }

底层实现中,Handler 会把 Pydantic 模型经model_json_schema()转换为 Gemini 的Schema(工具函数位于 instructor/v2/providers/gemini/utils.py 与map_to_genai_schema),JSON模式下直接作为response_schema下发(handlers.py),保证输出结构与模型定义严格对齐。

流式输出

Instructor 提供两种流式方案,按需选用:

  1. Iterables:流式提取同一类型的多个对象(例如从一段文本中提取多个用户);
  2. Partial Streaming:流式处理单个对象,边生成边消费部分结果。

Partials(部分流式)

create_partial返回一个生成器,随着 token 逐步到达,字段会从None逐渐填充完整:

import instructor from pydantic import BaseModel client = instructor.from_provider( "google/gemini-3.8-flash", ) class User(BaseModel): name: str age: int bio: str user = client.create_partial( messages=[ { "role": "user", "content": "Create a user profile for Jason and 1 sentence bio, age 25", }, ], response_model=User, ) for user_partial in user: print(user_partial) #> name=None age=None bio=None #> name=None age=25 bio='Jason is a great guy' #> name='Jason' age=25 bio='Jason is a great guy'

Iterable(迭代流式)

create_iterable从单个响应中逐个产出同类型对象:

import instructor from pydantic import BaseModel client = instructor.from_provider( "google/gemini-3.8-flash", ) class User(BaseModel): name: str age: int # Extract multiple users from text users = client.create_iterable( messages=[ { "role": "user", "content": """ Extract users: 1. Jason is 25 years old 2. Sarah is 30 years old 3. Mike is 28 years old """, }, ], response_model=User, ) for user in users: print(user) #> name='Jason' age=25 #> name='Sarah' age=30 #> name='Mike' age=28

流式的底层逻辑同样位于 handlers.py:extract_streaming_json逐块抽取 JSON(TOOLS模式下取function_call.argsJSON模式下取文本),再由from_streaming_response增量构建 Pydantic 对象(L210-L322)。异步场景使用create_partial/create_iterable+async for同样可行,相关完整示例见 docs/integrations/genai.md。

补充说明:GenAI 的Mode.TOOLS(函数调用)与流式存在兼容性约束,若需流式请优先使用Mode.JSON,或显式使用Partial[YourModel]

已知限制:Union 类型

Gemini 与 Instructor 配合时存在以下已知限制:

  1. Union 类型:Gemini 不支持 Union 类型(Optional除外)。请改用独立响应模型或Literal类型;X | None形式的可选字段可以正常工作;
  2. Union 流式:Iterable 流式不支持 Union 类型。

这些限制是 Gemini 平台特有的,不影响 OpenAI、Anthropic 等其他 Provider。仓库的测试会自动跳过 Gemini 的这些特性以避免失败。可参考 docs/integrations/genai.md 中的 Union 注意事项,以及 instructor/v2/providers/gemini/utils.py 中 Schema 转换对anyOf仅接受"单类型 + null"组合的处理逻辑。

Instructor Modes:TOOLS 与 JSON

针对 Gemini 的不同响应机制,Instructor 提供两种通用模式:

模式实现机制说明
instructor.Mode.TOOLSGemini 函数调用(tool calling)API默认模式,将响应模型声明为 FunctionDeclaration
instructor.Mode.JSONGemini 的 JSON Schema 模式通过response_schema强制 JSON 输出
  • 向后兼容:遗留的 Provider 专属模式(如Mode.GENAI_TOOLSMode.GENAI_JSONMode.GENAI_STRUCTURED_OUTPUTS)已弃用,会发出警告并自动映射到通用模式(Mode.TOOLSMode.JSON)。映射表定义在 instructor/v2/core/mode.py 的DEPRECATED_TO_CORE中。
  • 模式选择:使用from_provider时,Instructor 会根据 Provider 与模型能力自动选择合适模式,一般无需手动指定;from_provider("google/...")的默认模式为Mode.TOOLS(见 auto_client.py)。

TOOLS模式下,GenAIToolsHandler(handlers.py)将 Pydantic 模型构造成FunctionDeclaration,并通过ToolConfig(FunctionCallingConfigMode.ANY)强制模型只调用该函数;JSON模式下,GenAIStructuredOutputsHandler(L455-L523)则设置response_mime_type: "application/json"response_schema。两种模式下,Pydantic 校验失败都会触发自动 reask(重试),将错误信息回传给模型修正。

另外,TOOLS模式会自动过滤 Gemini 响应中的思考片段(thought parts),避免内部推理内容干扰结构化解析——这在 Gemini 2.5 及以上默认开启思考的模型中尤为重要。

可用模型概览

Google 提供多款 Gemini 模型供不同场景选择:

  • Gemini Flash:通用目的,推理速度快,适合高频提取;
  • Gemini Pro:高级推理与多模态,适合复杂任务;
  • Gemini Flash-8b:轻量、性价比高,适合大规模低成本调用。

具体以 Google 当前可用的模型名为准(如仓库中广泛使用的google/gemini-2.5-flash),传入from_provider("google/<model>")即可。

多模态能力延伸

Gemini 的多模态(图片、音频、PDF、视频)是 Instructor 集成的重点场景,仓库提供了多篇深入指南:

  • 使用 Gemini 提取旅行视频推荐
  • 用 Gemini 解析 PDF
  • 用 Gemini 生成 PDF 引用

这些文章展示了ImageAudioPDFPDFWithGenaiFile(配合 Gemini Files API)与create/create_partial的组合用法;多模态媒体的统一加载 API(URL / 本地路径 / base64 / 自动检测)实现在 instructor/v2/core/multimodal.py,Provider 专属编码在 instructor/v2/providers/genai/multimodal.py。开启autodetect_images=True后,字符串形式的文件路径与 URL 会在请求中自动转换为媒体 Part。

从旧 SDK 迁移

从 google-generativeai 迁移

如果你仍在使用旧的google-generativeai包(gemini/前缀):

# 旧方式(已弃用) import instructor client = instructor.from_provider( "google/gemini-3.8-flash", mode=instructor.Mode.JSON, )

推荐迁移方式:

import instructor # 方式一:使用 from_provider(推荐) client = instructor.from_provider("google/gemini-3.8-flash") # 方式二:直接使用 from_genai(遗留/进阶用法) from google import genai from instructor import from_genai client = from_genai(genai.Client())

from_genai接收一个原生google.genai.Client实例并返回 Instructor 客户端(instructor/v2/providers/genai/client.py),适合需要保留 Google 原生请求格式或已有genai.Client实例的场景。它也要求传入的必须是google.genai.Client实例,否则会抛出ClientError

Vertex AI 迁移

Vertex AI 用户的迁移路径类似:

# 旧方式(已弃用) import instructor import vertexai vertexai.init(project="your-project", location="us-central1") client = instructor.from_provider( "google/gemini-3.8-flash", vertexai=True, mode=instructor.Mode.TOOLS, )

推荐方式:

import instructor # 方式一:使用 from_provider(推荐) client = instructor.from_provider( "vertexai/gemini-3.8-flash", project="your-project", location="us-central1" ) # 方式二:使用 from_genai + vertexai=True(遗留/进阶用法) from google import genai from instructor import from_genai client = from_genai( genai.Client(vertexai=True, project="your-project", location="us-central1") )

_build_google会从kwargs提取projectlocationcredentials等参数并透传给genai.Client(vertexai=...)(auto_client.py),因此通过from_providervertexai=Trueprojectlocation即可无缝切换 Gemini API 与 Vertex AI。

相关资源

  • 快速上手:快速开始指南
  • from_provider 详解:客户端配置的详细说明
  • Instructor 核心概念 与 类型校验指南
  • 多模态示例:视觉与多模态处理
  • 各 Provider 示例:所有 Provider 的快速示例
  • 更新与兼容性说明:Instructor 会持续跟进 Google 最新 API 版本,升级前请查阅变更日志

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

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

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

鸽巢原理在Codeforces刷题中的实战指南:从余数抽屉到值域桶

昨晚又卡在了一道 Div2 C 上&#xff0c;看到题解第一行写着 “By Pigeonhole Principle”&#xff0c;差点没把键盘拍烂。鸽巢原理&#xff0c;这个名字我在入门书里见过&#xff0c;但说实在的&#xff0c;真正在 Codeforces 上刷题时&#xff0c;我很少第一时间往这个方向想…

作者头像 李华
网站建设 2026/9/15 18:24:16

电力系统动态状态估计与鲁棒IEKF实现

1. 电力系统动态状态估计的挑战与需求电力系统动态状态估计是现代电网运行控制中的核心技术之一。作为一名在电力系统自动化领域工作多年的工程师&#xff0c;我深刻理解这项技术在实际应用中的重要性。简单来说&#xff0c;动态状态估计就是通过实时测量数据来推断电力系统的运…

作者头像 李华
网站建设 2026/9/15 18:24:16

北京学会网站建设实战:3步搞定域名与服务器避坑指南

北京学会网站建设实战:3步搞定域名与服务器避坑指南 做学会网站,最让人头大的是什么?不是内容排版,也不是功能开发,而是 域名服务器搞不懂 。很多北京地区的学会负责人在拿到 建站报价…

作者头像 李华
网站建设 2026/9/15 18:23:11

bottom 怎么安装 shell 自动补全文件?

bottom 怎么安装 shell 自动补全文件&#xff1f; 【免费下载链接】bottom Yet another cross-platform graphical process/system monitor. 项目地址: https://gitcode.com/GitHub_Trending/bo/bottom bottom&#xff08;btm&#xff09;是一款跨平台的图形化进程/系统…

作者头像 李华
网站建设 2026/9/15 18:22:41

恶意PDF病毒木马拆解:结构分析、检测技术与防御实践

PDF这玩意儿&#xff0c;平时看着人畜无害&#xff0c;谁天天办公不跟它打交道。但恰恰是这种“天天见”的文件格式&#xff0c;成了病毒木马渗透里最爱用的载体之一。我处理过不少终端中招的案例&#xff0c;溯源到最后&#xff0c;入口往往不是那个刺眼的exe&#xff0c;而是…

作者头像 李华