跳到内容

使用 Instructor 和 OpenAI 实现结构化输出,完整指南

OpenAI 是 Instructor 的主要集成,为 GPT-3.5、GPT-4 及未来的模型提供强大的结构化输出支持。本指南涵盖了使用 Instructor 与 OpenAI 实现类型安全、经过验证的响应所需的一切信息。

快速开始

Instructor 开箱即用支持 OpenAI,您无需额外安装任何东西。

pip install "instructor"

⚠️ 重要:在使用客户端之前,必须设置您的 OpenAI API 密钥。您可以通过两种方式进行设置:

  1. 设置环境变量
export OPENAI_API_KEY='your-api-key-here'
  1. 或者直接提供给客户端
import os
from openai import OpenAI
client = OpenAI(api_key='your-api-key-here')

简单用户示例 (同步)

import os
from openai import OpenAI
import instructor
from pydantic import BaseModel

# Initialize with API key
client = OpenAI(api_key=os.getenv('OPENAI_API_KEY'))

# Enable instructor patches for OpenAI client
client = instructor.from_openai(client)

class User(BaseModel):
    name: str
    age: int

# Create structured output
user = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "user", "content": "Extract: Jason is 25 years old"},
    ],
    response_model=User,
)

print(user)
#> User(name='Jason', age=25)

简单用户示例 (异步)

import os
from openai import AsyncOpenAI
import instructor
from pydantic import BaseModel
import asyncio

# Initialize with API key
client = AsyncOpenAI(api_key=os.getenv('OPENAI_API_KEY'))

# Enable instructor patches for async OpenAI client
client = instructor.from_openai(client)

class User(BaseModel):
    name: str
    age: int

async def extract_user():
    user = await client.chat.completions.create(
        model="gpt-4-turbo-preview",
        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)

嵌套示例

from pydantic import BaseModel
from typing import List
import os
from openai import OpenAI
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]

# Initialize with API key
client = OpenAI(api_key=os.getenv('OPENAI_API_KEY'))

# Enable instructor patches for OpenAI client
client = instructor.from_openai(client)
# Create structured output with nested objects
user = client.chat.completions.create(
    model="gpt-4o-mini",
    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'
#>         }
#>     ]
#> }

多模态

我们提供了一些不同的示例文件供您测试这些新功能。以下所有示例均使用这些文件。

  • (音频) : 林肯葛底斯堡演说录音 : gettysburg.wav
  • (图片) : 一张蓝莓植物的图片 image.jpg
  • (PDF) : 一个包含虚假发票的示例 PDF 文件 invoice.pdf

Instructor 提供了一个统一的、与提供商无关的接口,用于处理图像、PDF 和音频文件等多模态输入。使用 Instructor 的多模态对象,您可以使用一致的 API 从 URL、本地文件或 base64 字符串轻松加载媒体,该 API 适用于不同的 AI 提供商(OpenAI、Anthropic、Mistral 等)。

Instructor 在幕后处理所有提供商特定的格式要求,确保您的代码随着提供商 API 的演进保持整洁和面向未来。

让我们看看如何使用 Image、Audio 和 PDF 类。

图像

有关 Image 组件更深入的介绍,请查看此处的文档

Instructor 使使用 OpenAI 的 GPT-4o 模型分析和提取图像中的语义信息变得容易。点击此处查看您想使用的模型是否具有视觉能力。

让我们看一个使用上面示例图像的例子,我们将使用 from_url 方法加载它。

请注意,我们也支持使用 from_pathfrom_base64 类方法加载本地文件和 base64 字符串。

from instructor.multimodal import Image
from pydantic import BaseModel, Field
import instructor
from openai import OpenAI


class ImageDescription(BaseModel):
    objects: list[str] = Field(..., description="The objects in the image")
    scene: str = Field(..., description="The scene of the image")
    colors: list[str] = Field(..., description="The colors in the image")


client = instructor.from_openai(OpenAI())
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/image.jpg"
# Multiple ways to load an image:
response = client.chat.completions.create(
    model="gpt-4o-mini",
    response_model=ImageDescription,
    messages=[
        {
            "role": "user",
            "content": [
                "What is in this image?",
                # Option 1: Direct URL with autodetection
                Image.from_url(url),
                # Option 2: Local file
                # Image.from_path("path/to/local/image.jpg")
                # Option 3: Base64 string
                # Image.from_base64("base64_encoded_string_here")
                # Option 4: Autodetect
                # Image.autodetect(<url|path|base64>)
            ],
        },
    ],
)

print(response)
# Example output:
# ImageDescription(
#     objects=['blueberries', 'leaves'],
#     scene='A blueberry bush with clusters of ripe blueberries and some unripe ones against a cloudy sky',
#     colors=['green', 'blue', 'purple', 'white']
# )

PDF

Instructor 使使用 OpenAI 的 GPT-4o 模型分析和提取 PDF 中的语义信息变得容易。

让我们看一个使用上面示例 PDF 的例子,我们将使用 from_url 方法加载它。

请注意,我们也支持使用 from_pathfrom_base64 类方法加载本地文件和 base64 字符串。

from instructor.multimodal import PDF
from pydantic import BaseModel, Field
import instructor
from openai import OpenAI


class Receipt(BaseModel):
    total: int
    items: list[str]


client = instructor.from_openai(OpenAI())
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/invoice.pdf"
# Multiple ways to load an PDF:
response = client.chat.completions.create(
    model="gpt-4o-mini",
    response_model=Receipt,
    messages=[
        {
            "role": "user",
            "content": [
                "Extract out the total and line items from the invoice",
                # Option 1: Direct URL
                PDF.from_url(url),
                # Option 2: Local file
                # PDF.from_path("path/to/local/invoice.pdf"),
                # Option 3: Base64 string
                # PDF.from_base64("base64_encoded_string_here")
                # Option 4: Autodetect
                # PDF.autodetect(<url|path|base64>)
            ],
        },
    ],
)

print(response)
# > Receipt(total=220, items=['English Tea', 'Tofu'])

音频

Instructor 使使用 OpenAI 的 GPT-4o 模型分析和提取音频文件中的语义信息变得容易。让我们看一个使用上面示例音频文件的例子,我们将使用 from_url 方法加载它。

请注意,我们也支持使用 from_path 加载本地文件和 base64 字符串。

from instructor.multimodal import Audio
from pydantic import BaseModel
import instructor
from openai import OpenAI


class AudioDescription(BaseModel):
    transcript: str
    summary: str
    speakers: list[str]
    key_points: list[str]


url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/gettysburg.wav"

client = instructor.from_openai(OpenAI())

response = client.chat.completions.create(
    model="gpt-4o-audio-preview",
    response_model=AudioDescription,
    modalities=["text"],
    audio={"voice": "alloy", "format": "wav"},
    messages=[
        {
            "role": "user",
            "content": [
                "Please transcribe and analyze this audio:",
                # Multiple loading options:
                Audio.from_url(url),
                # Option 2: Local file
                # Audio.from_path("path/to/local/audio.mp3")
            ],
        },
    ],
)

print(response)
# > transcript='Four score and seven years ago our fathers..."]

流式支持

Instructor 提供两种主要方式来流式输出响应

  1. 可迭代对象 (Iterables):当您想流式传输同一类型的对象列表时,这些对象非常有用(例如,使用结构化输出提取多个用户)
  2. 局部流式传输 (Partial Streaming):当您想流式传输单个对象并希望在响应传入时立即开始处理时,这非常有用。

局部解析

from instructor import from_openai
import openai
from pydantic import BaseModel

client = from_openai(openai.OpenAI())


class User(BaseModel):
    name: str
    age: int
    bio: str


user = client.chat.completions.create_partial(
    model="gpt-4o-mini",
    messages=[
        {"role": "user", "content": "Create a user profile for Jason, age 25"},
    ],
    response_model=User,
)

for user_partial in user:
    print(user_partial)

# > name='Jason' age=None bio='None'
# > name='Jason' age=25 bio='A tech'
# > name='Jason' age=25 bio='A tech enthusiast'
# > name='Jason' age=25 bio='A tech enthusiast who loves coding, gaming, and exploring new'
# > name='Jason' age=25 bio='A tech enthusiast who loves coding, gaming, and exploring new technologies'

可迭代示例

import os
from openai import OpenAI
import instructor
from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int

# Extract multiple users from text
users = client.chat.completions.create_iterable(
    model="gpt-4o-mini",
    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

Instructor 模式

我们提供了几种模式,以便轻松使用 OpenAI 支持的不同响应模型

  1. instructor.Mode.TOOLS : 这使用工具调用 API 向客户端返回结构化输出
  2. instructor.Mode.JSON : 这通过使用OpenAI 的 JSON 模式强制模型返回 JSON。
  3. instructor.Mode.FUNCTIONS : 这使用 OpenAI 的函数调用 API 返回结构化输出,将来将被弃用。
  4. instructor.Mode.PARALLEL_TOOLS : 这使用并行工具调用 API 向客户端返回结构化输出。这允许模型在单个响应中生成多个调用。
  5. instructor.Mode.MD_JSON : 这对 OpenAI 聊天完成 API 进行简单调用,并将原始响应解析为 JSON。
  6. instructor.Mode.TOOLS_STRICT : 这使用新的 OpenAI 结构化输出 API,通过受限语法采样向客户端返回结构化输出。这限制用户只能使用 JSON schema 的一个子集。
  7. instructor.Mode.JSON_O1 : 这是 O1 模型的一种模式。我们创建了一个新模式,因为 O1 不支持任何系统消息、工具调用或流式传输,因此您需要使用此模式才能将 Instructor 与 O1 一起使用。

总的来说,我们建议使用 Mode.Tools,因为它最灵活且面向未来。它拥有一组最大的特性集,您可以在其中指定 schema,并且使工作变得显著容易。

批量 API

我们也支持使用 create_batch 方法批量处理请求。如果您的请求对时间不敏感,这很有帮助,因为您可以获得 50% 的 token 成本折扣。

在此处阅读更多关于如何使用它的信息

最佳实践

  1. 模型选择 : 对于更简单的用例,我们建议使用 gpt-4o-mini,因为它便宜且非常适合结构化输出的明确目标。当任务更模糊时,请考虑根据您的需求升级到 4o 甚至 O1

  2. 性能优化 : 流式处理响应模型更快,应该从一开始就这样做。如果您使用简单的响应模型,尤其如此。

常见用例

  • 数据提取
  • 表单解析
  • API 响应结构化
  • 文档分析
  • 配置生成

更新与兼容性

Instructor 与最新的 OpenAI API 版本和模型保持兼容。查看变更日志以获取更新。