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

为什么在 MLflow 中使用 DSPy?
DSPy 库与 MLflow 的原生集成有助于用户管理 DSPy 的开发生命周期。以下是使用 MLflow 中的 DSPy 的一些主要优势:
- MLflow Tracking 允许您跟踪 DSPy 程序的训练和执行。借助 MLflow API,您可以记录各种制品并组织训练运行,从而提高对模型性能的可见性。
- MLflow Model 将编译后的 DSPy 程序与其依赖版本、输入输出接口和其他重要元数据打包在一起。这使您可以轻松部署编译后的 DSPy 程序,并确信在 ML 生命周期不同阶段的环境是一致的。
- MLflow Evaluate 在 MLflow 中提供了评估 GenAI 应用程序的原生功能。此功能有助于高效评估 DSPy 编译程序的推理结果,确保稳健的性能分析并促进快速迭代。
- MLflow Tracing 是一款强大的可观测性工具,用于监控和调试 DSPy 模型内部发生的情况,帮助您快速识别潜在的瓶颈或问题。凭借其强大的自动记录功能,您无需添加任何代码,只需运行一个命令即可检测您的 DSPy 应用程序。
开始使用
在本入门教程中,您将学习 DSPy 最基本组件,以及如何利用与 MLflow 的集成来存储、检索和使用 DSPy 程序。
概念
Module
Modules 是处理特定文本转换(例如回答问题或进行摘要)的组件。它们取代了传统的手写提示,并且可以从示例中学习,从而使其更具适应性。
Signature
一个 signature 是对模块输入和输出行为的自然语言描述。例如,“question -> answer” 指定模块应将问题作为输入并返回答案。
Optimizer
一个 optimizer 通过调整模块以满足性能指标来改进 LM 管道,无论是通过生成更好的提示还是微调模型。
Program
程序是一组连接成管道以执行复杂任务的模块。DSPy 程序具有灵活性,允许您使用编译器对其进行优化和调整。
自动跟踪

MLflow Tracing 是一款强大的功能,可让您监控和调试 DSPy 程序。使用 MLflow,只需在代码中调用 mlflow.dspy.autolog() 函数即可启用自动跟踪。
import mlflow
mlflow.dspy.autolog()
启用后,MLflow 将在您的 DSPy 程序执行时生成跟踪,并将它们记录在您的 MLflow 实验中。
在此处 了解更多 关于 MLflow DSPy 跟踪功能的信息。
在 MLflow 实验中跟踪 DSPy 程序
创建 DSPy 程序
Module 对象是 DSPy 和 MLflow 集成的核心。使用 DSPy,您可以通过一个或一组模块创建复杂的智能代理逻辑。
pip install mlflow 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.""",
}
MLflow PythonModel for DSPy 支持流式传输。要启用流式传输,请确保满足以下条件:
- 安装版本大于 2.6.23 的
dspy。 - 使用签名记录您的模型。
- 确保模型的所有输出都是字符串。
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 字典,并与模型工件一起进行 pickle。服务上下文是 GenAI 框架中推广的一个概念。简而言之,它存储了对项目全局的配置。对于 DSPy 而言,我们可以设置语言模型、重排器、适配器等信息。
DSPy 将此服务上下文存储在 Settings 单例类中。在记录模型时,在 Settings 对象中设置的敏感 API 访问密钥不会被持久化。在部署 DSPy 模型时,您必须确保部署环境中设置了这些密钥,以便您的 DSPy 模型能够对需要访问密钥的服务进行远程调用。