跳到内容

教程:保存和加载你的 DSPy 程序

本指南演示如何保存和加载你的 DSPy 程序。概括来说,有两种保存 DSPy 程序的方式

  1. 仅保存程序状态,类似于 PyTorch 中仅保存权重。
  2. 保存整个程序,包括架构和状态,此功能由 dspy>=2.6.0 支持。

仅保存状态

状态表示 DSPy 程序的内部状态,包括签名、demos(少量示例)以及其他信息,例如程序中每个 dspy.Predict 要使用的 lm。它还包括其他 DSPy 模块的可配置属性,例如 dspy.retrievers.Retrieverk。要保存程序状态,请使用 save 方法并设置 save_program=False。你可以选择将状态保存为 JSON 文件或 pickle 文件。我们建议将状态保存为 JSON 文件,因为它更安全且可读。但有时你的程序包含不可序列化的对象,例如 dspy.Imagedatetime.datetime,在这种情况下,你应该将状态保存为 pickle 文件。

假设我们已经用一些数据编译了一个程序,并且我们想保存该程序供将来使用

import dspy
from dspy.datasets.gsm8k import GSM8K, gsm8k_metric

dspy.settings.configure(lm=dspy.LM("openai/gpt-4o-mini"))

gsm8k = GSM8K()
gsm8k_trainset = gsm8k.train[:10]
dspy_program = dspy.ChainOfThought("question -> answer")

optimizer = dspy.BootstrapFewShot(metric=gsm8k_metric, max_bootstrapped_demos=4, max_labeled_demos=4, max_rounds=5)
compiled_dspy_program = optimizer.compile(dspy_program, trainset=gsm8k_trainset)

将程序状态保存到 json 文件

compiled_dspy_program.save("./dspy_program/program.json", save_program=False)

将程序状态保存到 pickle 文件

compiled_dspy_program.save("./dspy_program/program.pkl", save_program=False)

要加载你保存的状态,你需要**重新创建相同的程序**,然后使用 load 方法加载状态。

loaded_dspy_program = dspy.ChainOfThought("question -> answer") # Recreate the same program.
loaded_dspy_program.load("./dspy_program/program.json")

assert len(compiled_dspy_program.demos) == len(loaded_dspy_program.demos)
for original_demo, loaded_demo in zip(compiled_dspy_program.demos, loaded_dspy_program.demos):
    # Loaded demo is a dict, while the original demo is a dspy.Example.
    assert original_demo.toDict() == loaded_demo
assert str(compiled_dspy_program.signature) == str(loaded_dspy_program.signature)

或者从 pickle 文件加载状态

loaded_dspy_program = dspy.ChainOfThought("question -> answer") # Recreate the same program.
loaded_dspy_program.load("./dspy_program/program.pkl")

assert len(compiled_dspy_program.demos) == len(loaded_dspy_program.demos)
for original_demo, loaded_demo in zip(compiled_dspy_program.demos, loaded_dspy_program.demos):
    # Loaded demo is a dict, while the original demo is a dspy.Example.
    assert original_demo.toDict() == loaded_demo
assert str(compiled_dspy_program.signature) == str(loaded_dspy_program.signature)

保存整个程序

dspy>=2.6.0 开始,DSPy 支持保存整个程序,包括架构和状态。此功能由 cloudpickle 提供支持,cloudpickle 是一个用于序列化和反序列化 Python 对象的库。

要保存整个程序,请使用 save 方法并设置 save_program=True,并指定一个目录路径来保存程序,而不是文件名。我们需要一个目录路径,因为我们还会保存一些元数据,例如依赖版本以及程序本身。

compiled_dspy_program.save("./dspy_program/", save_program=True)

要加载已保存的程序,直接使用 dspy.load 方法

loaded_dspy_program = dspy.load("./dspy_program/")

assert len(compiled_dspy_program.demos) == len(loaded_dspy_program.demos)
for original_demo, loaded_demo in zip(compiled_dspy_program.demos, loaded_dspy_program.demos):
    # Loaded demo is a dict, while the original demo is a dspy.Example.
    assert original_demo.toDict() == loaded_demo
assert str(compiled_dspy_program.signature) == str(loaded_dspy_program.signature)

通过保存整个程序,你无需重新创建程序,而是可以直接加载架构以及状态。你可以根据需要选择合适的保存方法。

向后兼容性

对于 dspy<2.7 版本,我们不保证已保存程序的向后兼容性。例如,如果你使用 dspy==2.5.35 保存程序,加载时请确保使用相同版本的 DSPy 来加载程序,否则程序可能无法按预期工作。在不同版本的 DSPy 中加载已保存文件可能不会引发错误,但性能可能与保存程序时不同。

dspy>=2.7 开始,我们将在主要版本中保证已保存程序的向后兼容性,即在 dspy==2.7.0 中保存的程序应该可以在 dspy==2.7.10 中加载。