Instructor 批量结构化抽取指南:Serverless 内存批处理与多 Provider 轮询实战
2026/9/16 12:42:15 网站建设 项目流程

Instructor 批量结构化抽取指南:Serverless 内存批处理与多 Provider 轮询实战

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

用 Instructor 做批量结构化抽取,最扎手的两件事是:Serverless 里临时文件不好落盘,各家提供商的请求格式不统一。这篇指南基于instructor/batch/模块的BatchProcessor(批处理模块的统一入口:你只写一套代码,它按模型字符串里的提供商前缀自动路由),按创建、提交、轮询、解析、运维的批任务生命周期推进,帮你跑通 Serverless 内存批处理与多 Provider 批任务轮询。

先看清两个痛点:落盘与格式碎片化

传统批处理的路径是:把请求逐条序列化进.jsonl文件,再上传给提供商。这在 Serverless 运行时(Lambda、Cloud Functions)里很别扭——临时存储有配额、磁盘 I/O 拖慢冷启动、敏感的提示词数据还会短暂暴露在磁盘上。

第二刀砍在格式上。OpenAI 要json_schema严格模式,Anthropic 要tool_use工具调用,Google 支持内联提交。自己维护三套请求构造,改一个字段要动三处。

解法就两个词:内存化(请求进缓冲区不进磁盘)+统一接口(面向BatchProcessor编程,格式差异封装在底层)。

📥 创建:file_path=None 触发零磁盘 I/O 的内存批处理

创建批请求的入口签名:

create_batch_from_messages(messages_list, file_path=None, max_tokens=1000, temperature=0.1) -> str | io.BytesIO

两个分支行为不同:

  • 传字符串路径:每条BatchRequest以 JSONL 行追加写入磁盘,返回文件路径;
  • None:写入io.BytesIO(不接触磁盘的文件式字节缓冲区),写完自动把读取位置复位到开头,返回缓冲区。

拿一个从产品评测文本抽取Product的场景走一遍:

from pydantic import BaseModel from instructor.batch.processor import BatchProcessor class Product(BaseModel): """从产品评测文本中抽取的结构化字段。""" name: str rating: int issue: str processor = BatchProcessor("openai/gpt-4o-mini", Product) reviews = [ [{"role": "system", "content": "从产品评测文本中抽取结构化字段。"}, {"role": "user", "content": "X95 降噪耳机音质出色,但续航只有 4 小时,打 2 分"}], [{"role": "system", "content": "从产品评测文本中抽取结构化字段。"}, {"role": "user", "content": "K2 机械键盘手感很稳,就是价格偏高,给 4 分"}], [{"role": "system", "content": "从产品评测文本中抽取结构化字段。"}, {"role": "user", "content": "M3 鼠标用了两个月滚轮失灵,1 分"}], ] # file_path=None → 请求序列化进 BytesIO,全程不落盘 buffer = processor.create_batch_from_messages(reviews, file_path=None) buffer.seek(0) # 若中间做过预览读取,提交前务必复位 batch_id = processor.submit_batch(buffer)

默认参数值得记住:max_tokens=1000temperature=0.1,示例脚本通常显式收紧为max_tokens=100~200。提交前只有一条铁律:确保缓冲区读取位置在开头,否则上传的内容从偏移量开始,提供商端直接报错。

内存 vs 文件怎么选,看这张表:

维度内存方案(file_path=None文件方案(file_path="x.jsonl"
返回值io.BytesIO缓冲区文件路径字符串
磁盘行为无 I/O每条请求追加一行 JSONL
清理成本需手动os.remove,示例脚本靠finally兜底
适用场景Serverless、敏感数据、短生命周期任务大体积批任务、需要调试与审计留痕

🔀 提交:provider 前缀决定一切路由

BatchProcessor.__init__拿到模型字符串后执行model.split("/", 1),前段是提供商、后段是模型名;格式非法直接抛ValueError。随后get_provider工厂实例化对应 Provider,后续submit_batchget_batch_statusget_results全部委托给它。

以 OpenAI 为例,一次create的完整动作是:

  1. 构造消息对话列表(list[list[dict]]);
  2. 实例化BatchProcessor,由前缀自动识别提供商;
  3. 生成提供商格式 + JSON Schema 的 JSONL 批文件;
  4. submit_batch真实创建批任务;
  5. 把 batch ID 写入{provider}_batch_id.txtsave_id=False可关);
  6. 立即返回,不阻塞等待完成。

run_batch_test.py 就是按这条流程做的跨提供商验收脚本,子命令覆盖全生命周期:create(建任务存 ID)、list-batches(看已存 ID)、fetch(拉结果,--poll每 30 秒轮询、--max-wait默认 600 秒)、show-results(打印解析后的 Pydantic 对象)、list-modelshelp

export OPENAI_API_KEY="your-key" python run_batch_test.py create --model "openai/gpt-4o-mini" python run_batch_test.py fetch --provider openai --poll --max-wait 1200

注意 Google 的分支不走文件:create_google_batch直接submit_batch(messages_list=..., use_inline=True, ...)内联提交;未设GOOGLE_API_KEY时脚本打印警告并以模拟模式运行,而 OpenAI/Anthropic 缺 Key 会直接报错退出。

三大 Provider 差异,一张表收拢

Provider环境变量是否必需缺失时行为请求格式路径典型完成时限
OpenAIOPENAI_API_KEY报错退出文件 +json_schema严格模式数小时完成,保证 24h 内
AnthropicANTHROPIC_API_KEY报错退出文件 +extract_datatool_use多数批次 1 小时内
GoogleGOOGLE_API_KEY警告并降级模拟模式内联提交(use_inline=True24 小时执行上限

各提供商在脚本里登记的可测模型(list-models可直接查看):

  • OpenAIopenai/gpt-4o-miniopenai/gpt-4oopenai/gpt-4-turbo
  • Anthropicanthropic/claude-3-5-sonnet-20241022anthropic/claude-3-opus-20240229anthropic/claude-3-haiku-20240307
  • Googlegoogle/gemini-2.5-flashgoogle/gemini-2.0-flash-001google/gemini-pro

另有一条 Google 专属约束:真实批任务需要 GCS 存储桶,且桶必须与批任务同区域

⏳ 轮询:六态状态机与 10 秒循环

批任务是异步的,提交后不能立刻取结果。模块把各家的原始状态收拢进BatchStatus枚举,只有六个值:pendingprocessingcompletedfailedcancelledexpired。归一化映射长这样:

原始状态来源归一化后
validatingOpenAIpending
in_progress/finalizingOpenAIprocessing
in_progressAnthropicprocessing
completed/ended两家completed
cancelling/cancelledOpenAIcancelled
failed/expired两家同名透传

list_batches(limit=10)返回的BatchJobInfo也带这份归一化字段(statusraw_statustimestampsrequest_counts),所以代码里只需认六态。可运行的轮询循环:

import time while True: s = processor.get_batch_status(batch_id).get("status") if s == "completed": results = processor.get_results(batch_id) break if s in ("failed", "cancelled", "expired"): raise SystemExit(f"批任务终止:{s}") time.sleep(10) # 每 10 秒查一次

in_memory_batch_example.py 的轮询窗口是max_wait_time=300秒;run_batch_test.py fetch --poll则是 30 秒间隔、10 分钟默认上限。超时未终态时不要死等——记下 batch ID,稍后用 CLI 回查即可。

🧩 解析:Maybe/Result 结果模型四件套

get_results返回的不是裸对象,而是强制你显式处理成败的 Maybe/Result 联合类型(源自函数式编程:要么成功带值、要么失败带因,没有中间态):

BatchResult: TypeAlias = Union[BatchSuccess[Any], BatchError]
  • BatchSuccess[T]custom_id+ 已解析的result: T+success=True
  • BatchErrorcustom_id+error_type+error_message+ 原始raw_data+success=False

解析发生在parse_results:逐行读 JSONL,OpenAI 从response.body.choices[0].message.content取 JSON;Anthropic 优先取tool_use块的input,取不到再解析text块里的 JSON;模型校验不过或提供商报错,都落成BatchError不中断整批流程

拿到results后,四个工具函数(定义于 instructor/batch/utils.py)覆盖绝大多数消费场景:

from instructor.batch import ( filter_successful, filter_errors, extract_results, get_results_by_custom_id, ) ok = filter_successful(results) # 成功条目 bad = filter_errors(results) # 失败条目,带 error_type/error_message items = extract_results(results) # 直接拿 list[Product] by_id = get_results_by_custom_id(results) # {custom_id: BatchResult}

典型分工:入库走items,告警走bad,排查单条失败用by_id["request-2"]

运维:instructor batch CLI 免代码管理

建完任务不必回到 Python 里。CLI 命令族共七个:cancelcreatecreate-from-filedeletedownload-filelistresults,用--provider指定提供商(默认openai):

# 实时刷新任务表格(含状态、耗时、完成/失败计数) instructor batch list --provider openai --live instructor batch results --batch-id batch_123 --output-file results.jsonl --model "openai/gpt-4o-mini" instructor batch create-from-file --file-path batch_requests.jsonl --model "openai/gpt-4o-mini" instructor batch cancel --batch-id batch_123 --provider openai

几个实用细节:

  • list支持--limit(默认 10)、--poll(轮询间隔秒数)、--live(实时刷新)、--screen;状态、创建/开始时间、耗时都在这张表里,等于省去了单独的状态查询命令;
  • OpenAI 表头是 Completed/Failed/Total,Anthropic 表头是 Succeeded/Errored/Processing,对应BatchRequestCounts的归一化字段;
  • --use-anthropic是废弃标志,官方提示改用--model/--provider
  • delete只有 Anthropic 支持,对 OpenAI 执行会得到明确的不可用提示。

不写 Python 也可以建任务:instructor batch create --messages-file messages.jsonl --model "openai/gpt-4o-mini" --response-model "examples.User" --output-file batch_requests.jsonl先生成请求文件,再create-from-file提交。

底层机制:请求格式转换与 Provider 懒加载

格式转换藏在 instructor/batch/request.py 的save_to_file分发里,两家各有一套:

  • OpenAIto_openai_format生成POST /v1/chat/completions请求,response_format设为json_schemastrict: True,并递归给所有object类型补additionalProperties: false——这是 OpenAI 严格模式不收请求的头号原因;
  • Anthropicto_anthropic_format先把所有system角色消息合并为顶层system参数,再把 Pydantic Schema 包装成名为extract_data的工具,用tool_choice = {"type": "tool", "name": "extract_data"}强制模型走这条路径。

同一份Product模型,进两家门时长的样子完全不同,而你一行都不用改。

懒加载在 instructor/batch/providers/init.py:模块导入时用importlib.util.find_spec("openai")探测 SDK 是否存在,缺了就只把对应 Provider 置为None。这样import instructor不装 SDK 也不炸,直到你真正用到它才抛出OpenAI is not installed/Anthropic is not installed这类带指向性的错误。

🚑 故障速查

报错原因修复
Error: OPENAI_API_KEY environment variable is not set环境变量未设置export OPENAI_API_KEY='your-key'(Anthropic 同理换ANTHROPIC_API_KEY
Error: Model must be in format 'provider/model-name'模型串缺少斜杠写成openai/gpt-4o-mini形式
Unsupported provider: xyz路由不认识该前缀前缀用openaianthropicgoogle之一
OpenAI is not installed/Anthropic is not installed对应 SDK 未安装pip install openaipip install anthropic
Missing GCS_BUCKET (Google)真实 Google 批任务需要对象存储桶设置GCS_BUCKET环境变量,并确保与批任务同区域

一句话与延伸阅读

核心思想一句话:先统一接口,再按提供商适配——你面向BatchProcessor编程,前缀路由、格式转换、状态归一化都在模块内部完成。

延伸阅读(均为仓库相对路径):

  • 批量处理完整文档:docs/concepts/batch.md
  • CLI 命令详解:docs/cli/batch.md
  • 统一入口:instructor/batch/processor.py
  • 请求格式转换:instructor/batch/request.py
  • 状态与结果模型:instructor/batch/models.py
  • 结果工具函数:instructor/batch/utils.py
  • 内存批处理示例:examples/batch_api/in_memory_batch_example.py
  • 跨提供商测试脚本:examples/batch_api/run_batch_test.py

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

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询