跳到内容

使用 Instructor 增强 Python 函数:微调与蒸馏指南

介绍

准备深入探索使用 Python 函数微调特定任务语言模型的世界吧。我们将探讨 instructor.instructions 如何简化这个过程,使你想蒸馏的任务更高效、更强大,同时保留其原有功能和向后兼容性。

如果你想查看完整示例,请访问 examples/distillation

为何使用 Instructor?

想象一下,你正在开发一个后端服务,它混合使用了传统和新的机器学习实践,可能涉及包含多个函数调用、验证和数据处理的管道。听起来很麻烦,对吗?这就是 Instructor 的用武之地。它通过为你的函数添加一个装饰器来简化复杂过程,使其更高效、更易于管理。该装饰器会自动生成用于微调的数据集,并帮助你替换函数实现。

快速开始:如何使用 Instructor 的蒸馏功能

在我们深入细节之前,先看看使用 Instructor 的蒸馏功能将函数调用微调导出到 JSONL 文件有多简单。

import logging
import random
from pydantic import BaseModel
from instructor import Instructions  # pip install instructor

# Logging setup
logging.basicConfig(level=logging.INFO)

instructions = Instructions(
    name="three_digit_multiply",
    finetune_format="messages",
    # log handler is used to save the data to a file
    # you can imagine saving it to a database or other storage
    # based on your needs!
    log_handlers=[logging.FileHandler("math_finetunes.jsonl")],
)


class Multiply(BaseModel):
    a: int
    b: int
    result: int


# Define a function with distillation
# The decorator will automatically generate a dataset for fine-tuning
# They must return a pydantic model to leverage function calling
@instructions.distil
def fn(a: int, b: int) -> Multiply:
    resp = a * b
    return Multiply(a=a, b=b, result=resp)


# Generate some data
for _ in range(10):
    a = random.randint(100, 999)
    b = random.randint(100, 999)
    print(fn(a, b))
    #> a=444 b=204 result=90576
    #> a=194 b=489 result=94866
    #> a=199 b=467 result=92933
    #> a=967 b=452 result=437084
    #> a=718 b=370 result=265660
    #> a=926 b=144 result=133344
    #> a=847 b=570 result=482790
    #> a=649 b=227 result=147323
    #> a=487 b=180 result=87660
    #> a=665 b=400 result=266000

微调语言模型的复杂性

微调不仅仅是编写一个像 def f(a, b): return a * b 这样的函数。它需要详细的数据准备和日志记录。然而,Instructor 提供了内置的日志记录功能和结构化输出以简化此过程。

为何 Instructor 和蒸馏是游戏规则改变者

该库提供两个主要优势

  1. 效率:简化函数,将需求蒸馏到模型权重和少量代码中。
  2. 集成:通过提供一个包装现有函数的简单接口,便于结合经典机器学习和语言模型。

Instructor 在简化微调中的作用

from instructor import Instructions 功能非常省时。它会自动生成微调数据集,使其轻松模仿函数的行为。

日志输出与运行微调

日志输出如下所示

{
    "messages": [
        {"role": "system", "content": 'Predict the results of this function: ...'},
        {"role": "user", "content": 'Return fn(133, b=539)'},
        {
            "role": "assistant",
            "function_call": {
                "name": "Multiply",
                "arguments": '{"a":133,"b":539,"result":89509}',
            },
        },
    ],
    "functions": [
        {"name": "Multiply", "description": "Correctly extracted `Multiply`..."}
    ],
}

像这样运行微调

别忘了将你的 OpenAI Key 设置为环境变量

所有 instructor jobs 命令都假定你已经在 shell 中设置了 OPENAI_API_KEY 环境变量。你可以在 shell 中运行命令 export OPENAI_API_KEY=<在此插入 API Key> 来设置它

instructor jobs create-from-file math_finetunes.jsonl

下一步和未来计划

这是我计划的未来展望

from instructor import Instructions, patch

patch()  # (1)!


class Multiply(BaseModel):
    a: int
    b: int
    result: int


instructions = Instructions(
    name="three_digit_multiply",
)


@instructions.distil(model='gpt-3.5-turbo:finetuned-123', mode="dispatch")  # (2)!
def fn(a: int, b: int) -> Multiply:
    resp = a + b
    return Multiply(a=a, b=b, result=resp)
  1. 别忘了运行我们提供的 Instructor 包中的 patch() 命令。这有助于将内容自动序列化回我们想要的 `Pydantic`` 模型中。

  2. 别忘了将其替换为你新的模型 ID。OpenAI 在其仪表板的 Fine-tuning 标签下使用 ID ft:gpt-3.5-turbo-0613:personal::<id> 来标识微调过的模型

有了这个,你可以替换函数实现,使其保持向后兼容。你甚至可以想象使用不同的模型来完成不同的任务,或者通过使用原始函数并将其与蒸馏模型进行比较来验证和运行评估。

结论

我们已经看到了 Instructor 如何让你的生活更轻松,从微调到蒸馏。现在,如果你觉得“哇,我真希望有一个后端服务能持续地做这件事”,那么你很幸运!请访问 useinstructor.com 填写调查问卷,告诉我们你是谁。

如果你喜欢这些内容或想尝试 instructor,请访问 github 并给我们点赞!