跳过内容

有了谷歌新的 OpenAI 集成,我还需要 Instructor 吗?

谷歌最近为 Gemini 推出了 OpenAI 客户端兼容性功能。

虽然这通过简化 Gemini 模型交互对开发者来说是向前迈出的重要一步,但你仍然绝对需要 Instructor

如果你不熟悉 Instructor,它提供了一个简单的接口,用于从不同提供商的 LLM 获取结构化输出。

这使得在不同提供商之间切换、从语言模型获取可靠输出以及最终构建生产级 LLM 应用变得容易。

当前状态

新的集成提供了与 OpenAI 客户端的轻松集成,这意味着将 function calling 与 Gemini 模型一起使用变得更加容易。我们不再需要使用像 `vertexai` 或 `google.generativeai` 这样特定于 Gemini 的库来定义响应模型。

代码大致如下所示

from openai import OpenAI

client = OpenAI(
    base_url="https://generativelanguage.googleapis.com/v1beta/", api_key="YOUR_API_KEY"
)

response = client.chat.completions.create(
    model="gemini-1.5-flash",
    messages=[{"role": "user", "content": "Extract name and age from: John is 30"}],
)

虽然这看起来很方便,但存在三个主要限制,使得 `instructor` 仍然必不可少

1. 有限的 Schema 支持

当前实现仅支持简单的单层 Schema。这意味着你无法使用真实世界应用中常见的复杂嵌套 Schema。例如,以下代码将无法工作

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


class Users(BaseModel):
    users: list[User]  # Nested schema - will throw an error

2. 不支持 Function Calling 的流式输出

该集成不支持 function calling 的流式输出。如果你的应用依赖流式响应,这是一个重要的限制,而流式响应在以下场景中越来越常见:

  • 实时用户界面
  • 渐进式渲染
  • 长时间运行的提取任务

3. 不支持多模态

也许最大的限制是缺乏多模态支持。Gemini 的优势在于其处理多种输入类型(图像、视频、音频)的能力,但 OpenAI 兼容层不支持这一点。这意味着你无法做到:

  • 执行视觉问答
  • 从图像中提取结构化数据
  • 分析视频内容
  • 处理音频输入

为什么 Instructor 仍然必不可少

让我们看看 Instructor 如何解决这些问题。

1. 简易的 Schema 管理

构建应用时,轻松定义和实验不同的响应模型非常重要。在我们自己的实验中,我们发现将单个字段名从 `final_choice` 更改为 `answer` 使模型准确率从 4.5% 提高到 95%。

我们在响应模型中构建和命名字段的方式可以从根本上改变模型解释和响应查询的方式。手动编辑 Schema 会限制你在响应模型上迭代的能力,引入灾难性错误的可能,并限制你能从模型中榨取多少能力。

你可以通过 `instructor` 利用我们的 `from_gemini` 和 `from_vertexai` 集成,在 Gemini 中获得 Pydantic 的全部能力,而无需依赖 OpenAI 集成中有限的支持。

2. 流式输出支持

`instructor` 提供内置的流式输出支持,允许你在生成过程中流式传输部分结果。

流式输出的一个常见用例是提取具有相同结构的多个项目 - 例如:提取多个用户、提取多个产品、提取多个事件等。

使用 `instructor` 完成此操作相对容易

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

client = from_openai(
    OpenAI(
        api_key=os.getenv("GOOGLE_API_KEY"),
        base_url="https://generativelanguage.googleapis.com/v1beta/",
    ),
    mode=Mode.MD_JSON,
)


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


resp = client.chat.completions.create_iterable(
    model="gemini-1.5-flash",
    messages=[
        {
            "role": "user",
            "content": "Generate 10 random users",
        }
    ],
    response_model=User,
)

for r in resp:
    print(r)
# name='Alice' age=25
# name='Bob' age=32
# name='Charlie' age=19
# name='David' age=48
# name='Emily' age=28
# name='Frank' age=36
# name='Grace' age=22
# name='Henry' age=41
# name='Isabella' age=30
# name='Jack' age=27

如果你想在项目生成时流式输出,可以使用 `create_partial` 方法来代替

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

client = from_openai(
    OpenAI(
        api_key=os.getenv("GOOGLE_API_KEY"),
        base_url="https://generativelanguage.googleapis.com/v1beta/",
    ),
    mode=Mode.MD_JSON,
)


class Story(BaseModel):
    title: str
    summary: str


resp = client.chat.completions.create_partial(
    model="gemini-1.5-flash",
    messages=[
        {
            "role": "user",
            "content": "Generate a random bedtime story + 1 sentence summary",
        }
    ],
    response_model=Story,
)

for r in resp:
    print(r)


# title = None summary = None
# title='The Little Firefly Who Lost His Light' summary=None
# title='The Little Firefly Who Lost His Light' summary='A tiny firefly learns the true meaning of friendship when he loses his glow and a wise old owl helps him find it again.'

3. 多模态支持

`instructor` 支持 Gemini 模型的多模态输入,允许你执行视觉问答、图像分析等任务。

你可以查看使用 Instructor 和 Gemini 从视频中提取旅行建议的示例文章。

Instructor 还提供什么?

除了解决 Gemini 新的 OpenAI 集成的核心限制外,Instructor 还提供一系列功能,使其成为生产级应用不可或缺的工具。

1. 提供商无关的 API

在不同提供商之间切换不应该需要重写整个代码库。使用 Instructor,只需修改几行代码即可轻松完成。

from openai import OpenAI
from instructor import from_openai

client = from_openai(
    OpenAI()
)

# rest of code

如果想切换到 Anthropic,只需更改以下代码行即可

from anthropic import Anthropic
from instructor import from_anthropic

client = from_anthropic(Anthropic())

# rest of code

2. 自动验证和重试

生产应用需要可靠的输出。Instructor 通过根据你想要的响应模型验证所有输出并自动重试验证失败的输出,来处理这个问题。

借助我们的重试集成,你可以完全控制重试(如果需要),轻松实现指数退避等机制和其他重试策略。

import openai
import instructor
from pydantic import BaseModel
from tenacity import Retrying, stop_after_attempt, wait_fixed

client = instructor.from_openai(openai.OpenAI(), mode=instructor.Mode.TOOLS)


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


response = client.chat.completions.create(
    model="gpt-4o-mini",
    response_model=UserDetail,
    messages=[
        {"role": "user", "content": "Extract `jason is 12`"},
    ],
    # Stop after the second attempt and wait a fixed 1 second between attempts
    max_retries=Retrying(
        stop=stop_after_attempt(2),
        wait=wait_fixed(1),
    ),
)
print(response.model_dump_json(indent=2))
"""
{
  "name": "jason",
  "age": 12
}
"""

结论

虽然谷歌的 OpenAI 兼容层是一个受欢迎的补充,但目前你可能仍有几个理由选择继续使用 Instructor。

在一个单独的包中,你可以获得诸如提供商无关的 API、流式输出能力、多模态支持、自动重新询问等功能。

立即通过 `pip install instructor` 安装并尝试一下,看看为什么 Pydantic 就是生产级 LLM 应用所需的全部。