跳到内容

订阅我们的时事通讯,获取更新和技巧

简单的合成数据生成

人们使用 Instructor 的目的是生成合成数据,而不是提取数据本身。我们甚至可以使用 J-Schemo 的额外字段来提供特定示例,以控制如何生成数据。

考虑下面的示例。我们很可能会生成非常简单的名称。

from typing import Iterable
from pydantic import BaseModel
import instructor
from openai import OpenAI


# Define the UserDetail model
class UserDetail(BaseModel):
    name: str
    age: int


# Patch the OpenAI client to enable the response_model functionality
client = instructor.from_openai(OpenAI())


def generate_fake_users(count: int) -> Iterable[UserDetail]:
    return client.chat.completions.create(
        model="gpt-3.5-turbo",
        response_model=Iterable[UserDetail],
        messages=[
            {"role": "user", "content": f"Generate a {count} synthetic users"},
        ],
    )


for user in generate_fake_users(5):
    print(user)
    #> name='Alice' age=25
    #> name='Bob' age=30
    #> name='Charlie' age=35
    #> name='David' age=40
    #> name='Eve' age=22

利用简单示例

我们可能希望通过利用 Pydantic 的配置,将示例作为提示的一部分。我们可以直接在 JSON 方案本身中设置示例。

from typing import Iterable
from pydantic import BaseModel, Field
import instructor
from openai import OpenAI


# Define the UserDetail model
class UserDetail(BaseModel):
    name: str = Field(examples=["Timothee Chalamet", "Zendaya"])
    age: int


# Patch the OpenAI client to enable the response_model functionality
client = instructor.from_openai(OpenAI())


def generate_fake_users(count: int) -> Iterable[UserDetail]:
    return client.chat.completions.create(
        model="gpt-3.5-turbo",
        response_model=Iterable[UserDetail],
        messages=[
            {"role": "user", "content": f"Generate a {count} synthetic users"},
        ],
    )


for user in generate_fake_users(5):
    print(user)
    #> name='John Doe' age=25
    #> name='Jane Smith' age=30
    #> name='Michael Johnson' age=22
    #> name='Emily Davis' age=28
    #> name='David Brown' age=35

通过将名人姓名作为示例,我们转向生成包含知名人物的合成数据,摆脱了之前使用的简单单字名称。

利用复杂示例

为了有效地生成更具细微差别的合成示例,让我们升级到“gpt-4-turbo-preview”模型,并使用模型级别的示例而不是属性级别的示例

import instructor

from typing import Iterable
from pydantic import BaseModel, ConfigDict
from openai import OpenAI


# Define the UserDetail model
class UserDetail(BaseModel):
    """Old Wizards"""

    name: str
    age: int

    model_config = ConfigDict(
        json_schema_extra={
            "examples": [
                {"name": "Gandalf the Grey", "age": 1000},
                {"name": "Albus Dumbledore", "age": 150},
            ]
        }
    )


# Patch the OpenAI client to enable the response_model functionality
client = instructor.from_openai(OpenAI())


def generate_fake_users(count: int) -> Iterable[UserDetail]:
    return client.chat.completions.create(
        model="gpt-4-turbo-preview",
        response_model=Iterable[UserDetail],
        messages=[
            {"role": "user", "content": f"Generate `{count}` synthetic examples"},
        ],
    )


for user in generate_fake_users(5):
    print(user)
    #> name='Merlin' age=1000
    #> name='Saruman the White' age=700
    #> name='Radagast the Brown' age=600
    #> name='Elminster Aumar' age=1200
    #> name='Mordenkainen' age=850

利用描述

通过调整 Pydantic 模型中的描述,我们可以巧妙地影响生成的合成数据的性质。这种方法可以更细致地控制输出,确保生成的数据与我们的期望或要求更紧密地对齐。

例如,在我们的 `UserDetail` 模型中将 `name` 字段的描述指定为“花哨的法式名字”,可以引导生成过程产生符合此特定标准的名称,从而生成一个既多样化又适合特定语言特征的数据集。

import instructor

from typing import Iterable
from pydantic import BaseModel, Field
from openai import OpenAI


# Define the UserDetail model
class UserDetail(BaseModel):
    name: str = Field(description="Fancy French sounding names")
    age: int


# Patch the OpenAI client to enable the response_model functionality
client = instructor.from_openai(OpenAI())


def generate_fake_users(count: int) -> Iterable[UserDetail]:
    return client.chat.completions.create(
        model="gpt-3.5-turbo",
        response_model=Iterable[UserDetail],
        messages=[
            {"role": "user", "content": f"Generate `{count}` synthetic users"},
        ],
    )


for user in generate_fake_users(5):
    print(user)
    #> name='Jean Luc' age=30
    #> name='Claire Belle' age=25
    #> name='Pierre Leclair' age=40
    #> name='Amelie Rousseau' age=35
    #> name='Etienne Lefevre' age=28

开源和本地 LLM 的结构化输出

Instructor 扩展了其在语言模型方面的能力。它最初通过 OpenAI SDK 进行 API 交互,使用 Pydantic 进行结构化数据验证。现在,Instructor 支持多种模型和平台。

JSON 模式的集成提高了对视觉模型和开源替代方案的适应性。这使得它能够支持从 GPTMistralOllamaHugging Face 上的模型,并使用 llama-cpp-python

Instructor 现在支持基于云的 API 和本地模型进行结构化数据提取。开发者可以参考我们的 Patching 指南,了解如何在不同模型中使用 JSON 模式。

为了学习 Instructor 和 Pydantic,我们提供了一个关于 引导语言模型生成结构化输出 的课程。

以下部分展示了 Instructor 与平台和本地设置集成以在 AI 项目中生成结构化输出的示例。

与 Langsmith 的无缝支持

人们常误认为 LangChain 的 LangSmith 只兼容 LangChain 的模型。实际上,LangSmith 是一个统一的 DevOps 平台,用于开发、协作、测试、部署和监控 LLM 应用程序。在这篇博客中,我们将探讨如何结合 instructor 使用 LangSmith 来增强 OpenAI 客户端。

Weights and Biases 免费课程

我刚刚发布了一个关于 wits and biases 的免费课程。它涵盖了教程中的材料。请访问 wandb.courses 查看,它是免费开放给所有人的,时长不到一小时!

点击图片访问课程

Python 缓存入门

Instructor 让使用语言模型变得容易,但它们仍然需要大量的计算资源。

今天,我们将深入探讨如何优化 Instructor 代码,同时保持 Pydantic 模型提供的卓越开发体验 (DX)。我们将解决 Pydantic 模型缓存(通常与 pickle 不兼容)的挑战,并探索使用 functools.cache 等装饰器的解决方案。然后,我们将使用 diskcacheredis 定制装饰器,以支持持久缓存和分布式系统。

生成器和 LLM 流式传输

延迟至关重要,特别是在电子商务和像 ChatGPT 这样的新型聊天应用中。流式传输是无需更快的响应时间即可增强用户体验的解决方案。

那是什么让流式传输成为可能?是生成器!

使用 Pydantic 验证 LLM 引用

确保信息的准确性至关重要。这篇博客文章探讨了 Pydantic 强大而灵活的验证器如何通过引用验证来增强数据准确性。

我们将首先使用简单的子字符串检查来验证引用。然后,我们将使用 Instructor 本身驱动 LLM 来验证引用,并将答案与给定引用对齐。最后,我们将探讨如何使用这些技术生成准确响应的数据集。

使用 asyncioInstructor 在 Python 中异步处理 OpenAI

今天,我将向您介绍在 Python 中使用 asyncio 的各种方法。我们将把这些方法应用于使用 Instructor 批量处理数据,并学习如何使用 asyncio.gatherasyncio.as_completed 进行并发数据处理。此外,我们将探讨如何使用 asyncio.Semaphore 限制对服务器的并发请求数量。

使用微调 GPT-3.5 和密度链生成更智能的摘要

探索如何使用 Instructor 将像密度链这样的迭代方法提炼成一个单独的微调模型

在本文中,我们将指导您使用 Instructor 实现原始的密度链方法,然后展示如何将 GPT 3.5 模型提炼以匹配 GPT-4 的迭代摘要能力。使用这些方法,我们将延迟降低了 20 倍,成本降低了 50 倍,并保持了实体密度。

最后,您将获得一个 GPT 3.5 模型(使用 Instructor 强大的工具进行微调),它能够生成媲美密度链 [Adams 等人 (2023)] 有效性的摘要。一如既往,所有代码都可以在我们仓库的 examples/chain-of-density 文件夹中找到,供您参考。