大型语言模型(LLM)、智能体工作流和矢量存储变得越来越强大,而简化 AI 应用开发的框架也越来越受欢迎。DSPy 是一个工具包,它提供了通用模块,用 Python 代码配置来替代提示工程和直接输入自然语言。
一般来说,使用 LLM 或基础模型需要仔细的提示工程,用户需要调整文本提示以获得正确的输出。虽然这种方法可能有效,但耗时长、容易出错,而且会产生脆弱的工具链,在模型发布新版本时需要更新。LangChain 用于应用程序构建的链式语言模型和 LlamaIndex 等流行框架侧重于提高文本内的搜索能力。开发人员仍然需要具备微调提示的专业知识,并需要时间测试每个提示,以获得所需的输出结果。DSPy 通过编程方式引导和限制语言模型行为,从而简化了这一提示调整过程。
DSPy 专注于自动化提示构建的优化。为了取代提示黑客攻击和一次性合成数据生成器,DSPy 提供了通用优化器,即更新程序参数的算法。每当您修改代码、数据、断言或指标时,您都可以再次编译程序,DSPy 将进行提示优化以创建适合您更改的新有效提示。
有时,人们认为自动提示优化意味着创建一个系统,让 LLM 评论和改进用户生成的提示。这不是使用 LLM 的最有效方式。DSPy 利用 LLM 的想法生成能力来生成自己的提示。然后,它使用评估指标集测试这些变体,看看它们是否能更好地解决问题。如果它们在用户指定的指标上没有更好的表现,那么这些新提示就会被丢弃。这类似于一种进化算法,提示根据它们的适应性进行评估,并迭代改进。
DSPy 可以在几种不同类型的工作流和场景中发挥作用。其中最常用的一些是检索增强生成、多跳问题解答和文档摘要。
思维链(CoT) 提示通过要求模型将复杂任务分解为一系列逻辑步骤,最终实现解决方案,以模拟类似人类的推理过程。这些推理步骤被输入到模型的上下文窗口中,为其提供手头任务的更多基础,即使在复杂的场景中也通常会产生更好的响应。DSPy 通过让语言模型生成思维链提示和策略,并使用语言模型对其进行测试,以生成给定模型的最有效 CoT 提示来提供帮助。
检索增强生成 (RAG) 是一种方法,它允许 LLM 利用来自各个来源的大量知识库,查询其知识存储,以查找相关段落或内容并产生完善的响应。RAG 确保 LLM 即使没有在主题上进行原始训练,也能动态使用实时知识并给出正确答案。这种额外的能力会导致设置 RAG 管道时变得更加复杂。DSPy 提供了一种无缝的方法来设置提示管道,无论是生成有效提示(提示调整)还是在较小模型的情况下,微调模型权重本身。
DSPy 可以通过两种方式优化 RAG 管道:使用标记示例或使用引导法示例。标记示例是预先存在的、手动标记的示例,直接用于训练学生模型。在 DSPy 的上下文中,引导法意味着在教师和学生范式中使用语言模式。教师根据用户提供的几个提示生成新的训练示例。然后,这些引导示例与手动标记的示例一起使用或代替手动标记的示例来训练学生模块,直到它提供正确的答案。然后,生成正确响应的提示将在整个 DSPy 管道中迭代更新。
很多时候,单一的搜索查询不足以完成复杂的问题解答任务。流行的 HotPot Question Answering 数据集包含需要多次问题解析和检索才能回答的问题。例如:“Bill Nelson 作为有效载荷专家乘坐的航天飞机首次发射是在哪一年?”这个答案需要知道 Bill Nelson 乘坐的是哥伦比亚号航天飞机,然后能够确定哥伦比亚号首次飞行是在 1981 年。
在检索增强文献中,应对这一挑战的标准方法是构建多跳搜索系统。这些系统读取检索到的结果,然后在必要时生成额外的查询以收集额外的信息,直到得出最终答案。使用 DSPy,您可以通过几行代码以可靠的方式创建相同的系统,允许您更新模型并轻松地重新运行管道。
摘要将较长的文本压缩成较短的版本,同时仍然保留关键信息和主要观点。对于 LLM 来说,这是一项很强的技能,应用范围很广,从创建文章摘要到从冗长的文档中生成简洁的报告。
评估语言模型生成摘要的质量提出了重大挑战。与具有明确正确或错误答案的任务不同,摘要质量往往是主观的并且依赖于上下文。该模型需要平衡信息保留与简洁性,同时保留原始文本的语气和意图,并确保事实准确,不引入错误。适应不同类型的源材料和摘要目的构成了额外的挑战。DSPy 允许您使用标记的数据来调整摘要提示,以获得尽可能好的响应。
DSPy 有自己的一套词汇和术语,学习其中一些关键术语将有助于了解其总体架构。
编译: 此过程指的是 DSPy 将基于 Python 的程序转换为语言模型可以理解并高效执行的指令。
签名:这些是定义模块输入和输出类型的类,用于确保 DSPy 程序中不同模块之间的兼容性。一些签名的例子是任务,如输入问题并输出推理和答案,或者将文档作为输入并输出摘要。
优化器: DSPy 的此组件可针对您正在使用的特定语言模型(例如 GPT3.5-Turbo、GPT-4.0 或 Llama 3.1),对编译后的程序进行微调。优化器可确保您最大限度地提高程序的性能和准确性。在 DSPy 的旧版本中,优化器被称为提词器。DSPy 程序由多个语言模型调用组成,这些语言模型作为 DSPy 模块堆叠在一起。每个 DSPy 模块都具有三种内部参数:LM 权重、应该遵循的指令以及输入/输出行为的存储演示。
当给出一个指标时,DSPy 使用所有权重、指令和模型行为,通过多阶段优化算法创建优化的提示。这些可以结合梯度下降(用于语言模型权重)和离散语言模型驱动的优化,即用于制定或更新指令以及创建或验证演示。DSPy 演示类似于少样本示例,但它们的功能要强大得多。您可以根据自己的程序从头开始创建,也可以通过多种有效方式优化其创建和选择。
在很多情况下,编译产生的提示比人工编写的提示更好,因为优化器可以比人工尝试更多的东西,更系统地直接调整指标。
管道:“管道”是 DSPy 对一系列连接的模块的称呼,这些模块协同工作以完成复杂任务。例如,管道可以编制文章摘要,将其从源语言翻译成目标语言,然后用目标语言生成相关问题。
指标:DSPy 定义了几种不同的指标来衡量输出的性能。例如,您可能需要输出与您的标签完全匹配。在其他情况下,部分匹配可能适合您的需求。DSPy 提供的常用指标是语义 F1。这一指标衡量的是答案中包含了多少标签信息,以及答案中包含了多少标签目标答案之外的无关数据。如果需要不同的方式来衡量性能,您也可以提供自己的自定义指标。
开始使用 DSPy 就像调用 pip install dspy-ai 一样简单。大多数模型都可以通过云中的 API 使用或在本地运行,因此不需要特殊硬件。它可以在本地运行,也可以在托管的笔记本环境(例如 Google Colab 或 Watson Studio)上运行。
一个典型的 DSPy 检索增强生成管道由语言模型和检索模型组成。例如,要使用 OpenAI GPT-3.5 Turbo 作为语言模型,ColBERTV2 检索器作为检索模型,我们将配置 DSPy 如下:
签名是模板,允许您配置语言模型和检索模型的输入和输出字段的结构。例如,这段代码片段显示了用上下文提示语言模型和用结构提示检索模型的语法:
我们在上下文和答案字段中包含简短的描述,以定义更可靠的指南,说明模型将接收什么以及应该生成什么。
一旦定义了签名,您就可以运行程序,并使用适合的优化器为您的任务创建最佳提示。在 DSP 中,这一过程称为编译。编译程序会更新每个模块中存储的参数。在大多数情况下,这主要表现为收集和选择好的示范,以便包含在提示中。
编译需要:
• 训练集或引导示例。
• 验证指标。在 RAG 场景中,这将是一种衡量预测答案准确性以及检索到的上下文是否包含答案的方法。
• 特定的优化器用于生成要测试的提示。例如,BootstrapFewShot 优化器可用于生成提示,然后测试这些生成的提示。
要编译 DSPy 程序,您需要配置要使用的模型,并将这些模型传递给选定优化器的编译方法。例如,RAG 应用程序的程序将包含一个语言模型和一个检索模型。然后,这些模型将被传递给编译方法,优化器将使用检索到的数据为语言生成设置上下文。
然后,您定义一个指标来评估检索和语言模型。这个指标定义将被传递给一个优化器,比如 BootstrapFewShot 或 LabeledFewShot 优化器,以便在评估语言模型生成的提示时使用。最后,优化器编译一个自定义模块,其中包含您定义的前向方法以及训练数据集的自定义模块。
选择使用哪种优化器通常需要实验,但有一些指导准则:
• 如果示例很少(大约 10 个),则可以从 BootstrapFewShot 开始使用,生成新的训练数据。
• 如果您有更多数据,例如 50 个或更多示例,请尝试 BootstrapFewShotWithRandomSearch 在训练数据的随机部分上生成新的训练数据。
• 如果您需要非常高效的程序,可以使用 BootstrapFinetune 微调一个小型 LLM,来完成您的任务。
编译完程序并比较指标后,您可能会对结果感到满意。但您也可能会发现,根据所选择的指标,您不太满意最终程序或结果中的某些内容。关键在于迭代开发。DSPy 提供了工具,可以通过迭代数据、更新程序结构、所选指标以及优化器,逐步进行改进。
DSPy 是开源的,您可以检查代码,了解开发进度。StanfordNLP 网站Github 上的文档包含如何开始使用 DSPy 的文档以及多个分步教程和演示。