跳到内容

宣布 instructor=1.0.0

在过去 10 个月里,我们秉承‘易于尝试,易于删除’的原则构建了 instructor。我们通过使用 instructor 包修补 openai 客户端并添加诸如 response_modelmax_retriesvalidation_context 等新参数来实现这一点。因此,我坚信 instructor 是从 LLM API 获取结构化数据的最佳方式

但因此,我们在让类型工作良好同时提供更多开发时控制方面遇到了一些困难。我很高兴推出 1.0.0 版本,它在类型方面清理了 API,同时不牺牲易用性。

增长

在过去 10 个月里,我们经历了健康的增长,拥有超过 4000+ GitHub Star 和 100+ 贡献者,更重要的是,每月有 12 万次下载,2 万独立月访问者,以及每月 50 万次对我们文档的请求。

downloads

有什么新功能?

说实话,变化不大,您需要做的最简单的更改是将 instructor.patch 替换为 instructor.from_openai

import openai
import instructor

client = instructor.from_openai(openai.OpenAI())

不同的是,现在您希望放入 create 调用的任何默认参数都将通过 kwargs 传递给客户端。

如果您知道要传入 temperature、seed 或 model,您可以这样做。

import openai
import instructor

client = instructor.from_openai(
    openai.OpenAI(), model="gpt-4-turbo-preview", temperature=0.2
)

现在,无论何时调用 client.chat.completions.createmodeltemperature 都将传递给 openai 客户端!

没有新标准

当我刚开始做这个项目时,我的目标是确保我们不引入任何新标准。相反,我们的重点是保持与现有标准的兼容性。通过创建我们自己的客户端,我们可以无缝代理 OpenAI 的 chat.completions.create 和 Anthropic 的 messages.create 方法。这种方法允许我们为您的客户端提供平滑的升级路径,支持所有最新的模型和功能,只要它们可用。此外,此策略可保护我们免受潜在的下游更改的影响。

import openai
import anthropic
import litellm
import instructor
from typing import TypeVar

T = TypeVar("T")

# These are all ways to create a client
client = instructor.from_openai(openai.OpenAI())
client = instructor.from_anthropic(anthropic.Anthropic())
client = instructor.from_litellm(litellm.completion)

# all of these will route to the same underlying create function
# allow you to add instructor to try it out, while easily removing it
client.create(model="gpt-4", response_model=type[T]) -> T
client.chat.completions.create(model="gpt-4", response_model=type[T]) -> T
client.messages.create(model="gpt-4", response_model=type[T]) -> T

类型被正确推断

这是 instructor 的梦想,但由于对 openai 的修补,我无法让类型工作良好。现在,有了新的客户端,我们可以让类型工作良好!我们还添加了一些 create_* 方法,以便更轻松地创建可迭代对象和部分对象,并访问原始 completion。

调用 create

import openai
import instructor
from pydantic import BaseModel


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


client = instructor.from_openai(openai.OpenAI())

user = client.chat.completions.create(
    model="gpt-4-turbo-preview",
    messages=[
        {"role": "user", "content": "Create a user"},
    ],
    response_model=User,
)

现在如果您使用 ID,您可以看到类型被正确推断。

type

处理异步: await create

这也将与异步客户端正常工作。

import openai
import instructor
from pydantic import BaseModel


client = instructor.from_openai(openai.AsyncOpenAI())


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


async def extract():
    return await client.chat.completions.create(
        model="gpt-4-turbo-preview",
        messages=[
            {"role": "user", "content": "Create a user"},
        ],
        response_model=User,
    )

请注意,仅仅因为我们返回 create 方法,extract() 函数就会返回正确的用户类型。

async

返回原始 completion: create_with_completion

您也可以返回原始 completion 对象

import openai
import instructor
from pydantic import BaseModel


client = instructor.from_openai(openai.OpenAI())


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


user, completion = client.chat.completions.create_with_completion(
    model="gpt-4-turbo-preview",
    messages=[
        {"role": "user", "content": "Create a user"},
    ],
    response_model=User,
)

with_completion

流式传输部分对象: create_partial

为了处理流,我们仍然支持 Iterable[T]Partial[T],但为了简化类型推断,我们还添加了 create_iterablecreate_partial 方法!

import openai
import instructor
from pydantic import BaseModel


client = instructor.from_openai(openai.OpenAI())


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


user_stream = client.chat.completions.create_partial(
    model="gpt-4-turbo-preview",
    messages=[
        {"role": "user", "content": "Create a user"},
    ],
    response_model=User,
)

for user in user_stream:
    print(user)
    #> name=None age=None
    #> name=None age=None
    #> name=None age=None
    #> name=None age=25
    #> name=None age=25
    #> name=None age=25
    #> name='' age=25
    #> name='John' age=25
    #> name='John Smith' age=25
    #> name='John Smith' age=25
    # name=None age=None
    # name='' age=None
    # name='John' age=None
    # name='John Doe' age=None
    # name='John Doe' age=30

请注意,现在推断的类型是 Generator[User, None]

generator

流式传输可迭代对象: create_iterable

当我们想要提取多个对象时,我们会得到一个对象的可迭代集合。

import openai
import instructor
from pydantic import BaseModel


client = instructor.from_openai(openai.OpenAI())


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


users = client.chat.completions.create_iterable(
    model="gpt-4-turbo-preview",
    messages=[
        {"role": "user", "content": "Create 2 users"},
    ],
    response_model=User,
)

for user in users:
    print(user)
    #> name='John Doe' age=30
    #> name='Jane Smith' age=28
    # User(name='John Doe', age=30)
    # User(name='Jane Smith', age=25)

iterable

验证和错误处理

Instructor 始终支持验证和错误处理。但现在,我们在 create 调用中添加了一个新的 validation_context 参数。这允许您传入一个 ValidationContext 对象,该对象将传递给 response_model。这允许您向 response_model 添加自定义验证逻辑。

如果您想了解更多,请查看关于重试重新请求验证的文档。

多语言支持

虽然每种风格不同,但核心理念是相同的。通过与各语言流行的验证库对接,使其尽可能接近通用 API,我们可以支持所有语言的相同功能。

请查看

如果您有兴趣贡献,请查看贡献指南;如果您想用您的语言创建 instructor,请告诉我,我可以帮助推广并连接所有文档!