跳到内容

发布统一提供商接口

我们很高兴推出 Instructor 的一项重要增强功能:**`from_provider()`** 函数。虽然 Instructor 一直专注于提供强大的结构化输出,但我们观察到许多用户使用多个 LLM 提供商。这通常涉及为每个客户端进行重复的设置。

`from_provider()` 函数旨在简化这一过程,使其更容易初始化客户端并在不同的模型之间进行实验。

这项新功能提供了一种简化的、基于字符串的方法,可以为各种流行的 LLM 提供商初始化经过 Instructor 增强的客户端。

什么是 `from_provider()`?

`from_provider()` 函数充当创建 LLM 客户端的智能工厂。通过提供模型字符串标识符,例如 `"openai/gpt-4o"` 或 `"anthropic/claude-3-opus-20240229"`,该函数会处理必要的设置

  • 自动 SDK 检测:它能识别目标提供商(例如,OpenAI、Anthropic、Google、Mistral、Cohere)。
  • 客户端初始化:它动态导入所需的提供商特定 SDK 并初始化原生客户端(例如 `openai.OpenAI()` 或 `anthropic.Anthropic()`)。
  • Instructor 补丁应用:它自动将 Instructor 补丁应用到客户端,从而实现结构化输出、验证和重试机制。
  • 合理的默认值:它为每个提供商使用推荐的 `instructor.Mode` 设置,这些设置针对性能和能力(例如,工具使用或 JSON 模式,如适用)进行了优化。
  • 同步和异步支持:用户可以通过设置 `async_client=True` 标志来获取同步或异步客户端。

主要优势

`from_provider()` 函数旨在简化几种常见的工作流程

  • 模型比较:便于在不同模型或提供商之间快速切换,以评估特定任务的性能、成本或输出质量。
  • 多提供商策略:简化回退机制的实现或根据复杂性或成本等标准将查询路由到不同的 LLM,从而减少客户端管理开销。
  • 快速原型设计:在新提供商或模型开始时实现更快的设置。
  • 简化配置:减少集成多个 LLM 提供商的项目中的样板代码。

工作原理:深入探究

在内部,`from_provider()`(位于 `instructor/auto_client.py`)解析模型字符串(例如,`"openai/gpt-4o-mini"`)以识别提供商和模型名称。然后它使用条件逻辑来导入正确的库,实例化客户端,并应用适当的 Instructor 补丁。例如,对于 OpenAI 客户端的概念性处理将涉及导入 `openai` SDK 和 `instructor.from_openai`。

# Conceptual illustration of internal logic for OpenAI:
# (Actual implementation is in instructor/auto_client.py)

# if provider == "openai":
#     import openai
#     from instructor import from_openai, Mode
#
#     # 'async_client', 'model_name', 'kwargs' are determined by from_provider
#     native_client = openai.AsyncOpenAI() if async_client else openai.OpenAI()
#
#     return from_openai(
#         native_client,
#         model=model_name,
#         mode=Mode.TOOLS,  # Default mode for OpenAI
#         **kwargs,
#     )

如果找不到所需的软件包,该函数还会通过提醒用户安装缺失的软件包(例如,通过 `uv pip install openai`)来管理依赖关系。

示例用法

注意:请确保您的 API 密钥(例如,`OPENAI_API_KEY`、`ANTHROPIC_API_KEY`)已配置为环境变量以便运行此代码。

这是一个独立的示例,演示如何使用 `from_provider()` 从 google gemini 的 flash-2.0 模型中检索结构化输出。

import instructor
from pydantic import BaseModel
from typing import Iterable

# Define your data structure
class Person(BaseModel):
    name: str
    age: int

# Connect to any provider with a single line
client = instructor.from_provider("google/gemini-2.0-flash")

# Extract structured data
response = client.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": "Alice is 30 and Bob is 25.",
        }
    ],
    response_model=Iterable[Person],
)

for person in response:
    print(f"Name: {person.name}, Age: {person.age}")
# Output:
# Name: Alice, Age: 30
# Name: Bob, Age: 25

切换提供商就像更改字符串一样简单

# OpenAI
client = instructor.from_provider("openai/gpt-4.1")

# Anthropic (with version date)
client = instructor.from_provider("anthropic/claude-3-5-haiku-20241022")

借助统一的提供商接口,您现在可以轻松地在同一任务上对不同的模型进行基准测试。这在您需要执行以下操作时至关重要

  1. 比较不同提供商的响应质量
  2. 测试哪个模型提供最佳的结构化提取结果
  3. 优化速度与准确性的权衡
  4. 在提供商之间运行 A/B 测试而无需代码重构

您无需为每个提供商维护单独的代码库或复杂的切换逻辑,而是可以专注于重要的事情:为您的特定用例找到最佳模型。

异步支持

在构建需要保持响应性的生产应用程序时,异步处理至关重要。

Instructor 的统一提供商接口在初始化期间通过一个简单的 `async_client` 关键字来支持此工作流程。

client = instructor.from_provider("openai/gpt-4.1", async_client=True)

异步实现特别适用于 Web 服务器、批量处理作业或任何需要在不阻塞应用程序主线程的情况下提取结构化数据的场景。

以下是您可以实现的方法

import instructor
from pydantic import BaseModel
import asyncio

class UserProfile(BaseModel):
    name: str
    country: str

async def get_user_profile():
    # Initialise an asynchronous client
    async_client = instructor.from_provider(
        "openai/gpt-4.1-mini",
        async_client=True
    )

    # Extract data asynchronously
    profile = await async_client.chat.completions.create(
        messages=[{"role": "user", "content": "Extract: Maria lives in Spain."}],
        response_model=UserProfile
    )
    print(f"Name: {profile.name}, Country: {profile.country}")

if __name__ == "__main__":
    asyncio.run(get_user_profile())

提供商特定参数

一些提供商需要额外的参数以获得最佳性能。

Instructor 不会隐藏这些选项,而是允许您直接通过 from_provider 函数传递它们

# Anthropic requires max tokens
client = instructor.from_provider(
    "anthropic/claude-3-sonnet-20240229",
    max_tokens=1024
)

如果您以后想更改此参数,只需在 `client.chat.completions.create` 函数上再次设置即可。

类型补全

为了让您更容易找到正确的模型字符串,我们现在为这些新的模型-提供商初始化字符串提供了自动补全功能。

当您使用新的 `from_provider` 方法时,如下所示,此功能会自动提供给您。

告别混乱的模型版本控制,赶紧着手处理您的业务逻辑吧!

未来方向

`from_provider()` 函数为客户端初始化提供了一种便捷的方法。Instructor 仍然是您选择的 LLM 提供商客户端的轻量级包装器,用户始终保留手动初始化和修补客户端的灵活性,以实现更精细的控制,或者在使用此实用程序尚未涵盖的提供商时。

这个统一接口旨在平衡常见任务的易用性与 Instructor 底层灵活性,旨在使多提供商 LLM 开发更易于访问和高效。然而,要进一步简化多提供商工作流程还有很多工作要做。未来的努力可以集中在

  • 统一提示缓存 API:虽然 Instructor 支持 Anthropic 等提供商的提示缓存(另请参阅我们关于 Anthropic 提示缓存的博客文章和通用的提示缓存概念),但更标准化、跨提供商的 API 用于管理缓存行为可以显著简化成本和延迟的优化。
  • 统一多模态对象处理:Instructor 已经提供了一种强大的方式来处理不同提供商的多模态输入,如图像、音频和 PDF。然而,更高级别的统一 API 可以进一步抽象这些类型的提供商特定细节,从而使构建可以无缝切换(例如)OpenAI 和 Anthropic 的视觉能力的应用变得更加简单,而无需更改媒体对象的传递方式。

这些是 `instructor` 可以继续为在日益多样化的 LLM 生态系统中工作的开发者减少阻力的领域。

我们鼓励您在项目中使用 `from_provider()`,特别是在试验多个 LLM 时。随时欢迎对其他提供商或功能的反馈和建议。