MLflow DSPy 模块
dspy 模块正处于积极开发阶段,并被标记为实验性。公共 API 可能会发生变化,并且随着模块的发展,可能会添加新功能。
简介
DSPy 是一个用于算法优化 LM 提示和权重的框架。它旨在通过用模块化组件替换手工制作的提示字符串来改进提示工程过程。这些模块简洁、定义明确,并保持高质量和表现力,使提示创建更高效、更具可扩展性。通过参数化这些模块并将提示视为优化问题,DSPy 可以更好地适应不同的语言模型,可能超越专家手工制作的提示。这种模块化还使得探索复杂的管道更容易,允许根据特定任务或细微的指标来微调性能。

为什么要将 DSPy 与 MLflow 结合使用?
DSPy 库与 MLflow 的原生集成有助于用户管理 DSPy 的开发生命周期。以下是使用 MLflow 的 DSPy 的一些主要好处:
- MLflow 跟踪允许您跟踪您的 DSPy 程序的训练和执行。使用 MLflow API,您可以记录各种工件并组织训练运行,从而提高对模型性能的可见性。
- MLflow 模型将您编译的 DSPy 程序及其依赖项版本、输入和输出接口以及其他基本元数据打包在一起。这使您可以轻松部署编译后的 DSPy 程序,因为可以确保 ML 生命周期不同阶段的环境一致性。
- MLflow 评估在 MLflow 中提供了评估 GenAI 应用的原生功能。此功能有助于有效评估 DSPy 编译程序的推理结果,确保稳健的性能分析并促进快速迭代。
- MLflow 跟踪是一个强大的可观察性工具,用于监控和调试 DSPy 模型内部发生的情况,帮助您快速识别潜在的瓶颈或问题。凭借其强大的自动记录功能,您无需在 DSPy 应用程序中添加任何代码,只需运行一个命令即可进行检测。
开始使用
在本入门教程中,您将了解 DSPy 最基本组成部分,以及如何利用与 MLflow 的集成来存储、检索和使用 DSPy 程序。
概念
Module
模块是处理特定文本转换的组件,例如回答问题或总结。它们取代了传统的手写提示,可以从示例中学习,使其更具适应性。
Signature
一个签名是模块输入和输出行为的自然语言描述。例如,“question -> answer” 指定模块应将问题作为输入并返回答案。
Optimizer
一个优化器通过调整模块以满足性能指标来改进 LM 管道,方法是生成更好的提示或微调模型。
Program
程序是一组连接成管道以执行复杂任务的模块。DSPy 程序是灵活的,允许您使用编译器对其进行优化和调整。
自动跟踪
MLflow 跟踪功能允许您监控和调试您的 DSPy 程序。使用 MLflow,您只需在代码中调用 mlflow.dspy.autolog() 函数即可启用自动跟踪。
import mlflow
mlflow.dspy.autolog()
启用后,每当执行 DSPy 程序时,MLflow 都会生成跟踪并将其记录到您的 MLflow 实验中。
在此处了解更多关于 MLflow DSPy 跟踪功能的信息。
在 MLflow 实验中跟踪 DSPy 程序
创建 DSPy 程序
Module 对象是 DSPy 和 MLflow 集成的核心。使用 DSPy,您可以通过一个或一组模块创建复杂的代理逻辑。
pip install 'mlflow[genai]' dspy -U
import dspy
# Define our language model
lm = dspy.LM(model="openai/gpt-4o-mini", max_tokens=250)
dspy.settings.configure(lm=lm)
# Define a Chain of Thought module
class CoT(dspy.Module):
def __init__(self):
super().__init__()
self.prog = dspy.ChainOfThought("question -> answer")
def forward(self, question):
return self.prog(question=question)
dspy_model = CoT()
将程序记录到 MLflow
您可以使用 mlflow.dspy.log_model() 函数将 dspy.Module 对象记录到 MLflow 运行中。
我们还将指定一个模型签名。MLflow 模型签名定义了模型输入和输出的预期模式,确保模型推理期间的一致性和正确性。
import mlflow
# Start an MLflow run
with mlflow.start_run():
# Log the model
model_info = mlflow.dspy.log_model(
dspy_model,
name="model",
input_example="what is 2 + 2?",
)

加载模块进行推理
可以使用 mlflow.pyfunc.load_model() 函数将保存的模块加载回来进行推理。此函数提供了一个由 DSPy 模块支持的 MLflow Python 模型。
import mlflow
# Load the model as an MLflow PythonModel
model = mlflow.pyfunc.load_model(model_info.model_uri)
# Predict with the object
response = model.predict("What kind of bear is best?")
print(response)
{
"reasoning": """The question "What kind of bear is best?" is often associated with a
humorous reference from the television show "The Office," where the character Jim
Halpert jokingly states, "Bears, beets, Battlestar Galactica." However, if we consider
the question seriously, it depends on the context. Different species of bears have
different characteristics and adaptations that make them "best" in various ways.
For example, the American black bear is known for its adaptability, while the polar bear is
the largest land carnivore and is well adapted to its Arctic environment. Ultimately, the
answer can vary based on personal preference or specific criteria such as strength,
intelligence, or adaptability.""",
"answer": """There isn\'t a definitive answer, as it depends on the context. However, many
people humorously refer to the American black bear or the polar bear when discussing
"the best" kind of bear.""",
}
DSPy 的 MLflow PythonModel 支持流式传输。要启用流式传输,请确保满足以下条件:
- 安装的
dspy版本大于 2.6.23。 - 记录带有签名的模型。
- 确保模型的所有输出都是字符串。
stream_response = model.predict_stream("What kind of bear is best?")
for output in stream_response:
print(output)
{"predict_name": "prog.predict", "signature_field_name": "reasoning", "chunk": "The"}
{
"predict_name": "prog.predict",
"signature_field_name": "reasoning",
"chunk": " question",
}
{"predict_name": "prog.predict", "signature_field_name": "reasoning", "chunk": " of"}
{"predict_name": "prog.predict", "signature_field_name": "reasoning", "chunk": " what"}
{"predict_name": "prog.predict", "signature_field_name": "reasoning", "chunk": " kind"}
{"predict_name": "prog.predict", "signature_field_name": "reasoning", "chunk": " of"}
{"predict_name": "prog.predict", "signature_field_name": "reasoning", "chunk": " bear"}
{"predict_name": "prog.predict", "signature_field_name": "reasoning", "chunk": " is"}
{"predict_name": "prog.predict", "signature_field_name": "reasoning", "chunk": " best"}
{"predict_name": "prog.predict", "signature_field_name": "reasoning", "chunk": " is"}
...
要加载 DSPy 程序本身而不是 PyFunc 包装的模型,请使用 mlflow.dspy.load_model() 函数。
model = mlflow.dspy.load_model(model_uri)
优化器自动记录
MLflow DSPy 模块支持 DSPy 优化器的自动记录。有关详细信息,请参阅优化器自动记录页面。
常见问题
如何保存编译的模型与未编译的模型?
DSPy 通过更新各种 LLM 参数(如提示、超参数和模型权重)来编译模型以优化训练。虽然 MLflow 允许记录已编译和未编译的模型,但通常首选使用已编译的模型,因为它有望在实践中表现更好。
MLflow 可以序列化哪些内容?
当在 MLflow 中使用 mlflow.dspy.log_model() 或 mlflow.dspy.save_model() 时,DSPy 程序将被序列化并保存到跟踪服务器中,作为 .pkl 文件。这使得部署变得容易。在底层,MLflow 使用 cloudpickle 来序列化 DSPy 对象,但某些 DSPy 工件不可序列化。相关示例列在下面。
- API 令牌。这些应单独管理,并通过环境变量安全传递。
- DSPy 跟踪对象,它主要在训练期间使用,而不是在推理期间使用。
如何管理密钥?
使用 MLflow DSPy 模块序列化时,令牌会从设置对象中删除。用户有责任将所需的密钥安全地传递给部署环境。
DSPy settings 对象是如何保存的?
为确保程序的可重现性,服务上下文会转换为 Python 字典并与模型工件一起被 pickling。服务上下文是一个在 GenAI 框架中普及的概念。简而言之,它存储了对您的项目全局通用的配置。对于 DSPy 而言,我们可以设置语言模型、重排序器、适配器等信息。
DSPy 将此服务上下文存储在 Settings 单例类中。在记录模型时,设置在 Settings 对象中设置的敏感 API 访问密钥不会被持久化。在部署 DSPy 模型时,您必须确保部署环境中设置了这些密钥,以便您的 DSPy 模型可以向需要访问密钥的服务发出远程调用。