Press "Enter" to skip to content

了解DSPy内部:你需要了解的新语言模型编程框架

由斯坦福大学的研究人员创建,该框架提供了一种有趣的替代方案,替代了LangChain或LlamaIndex。

使用Midjourney创建

我最近开始了一个以人工智能为重点的教育通讯,已经有超过160,000个订阅者了。TheSequence是一个无废话(即无炒作、无新闻等)以机器学习为导向的通讯,阅读只需5分钟。其目标是让您了解最新的机器学习项目、研究论文和概念。请通过以下方式订阅并试试:

TheSequence | Jesus Rodriguez | Substack

机器学习、人工智能和数据领域的最佳信息来源…

thesequence.substack.com

语言模型编程(LMP)框架的范围在过去几个月内迅速扩大。诸如LangChain或LlamaIndex等框架在LLM社区内确实取得了相当高的采用率,而微软的语义核心则提供了令人印象深刻的能力集。最近,一种名为DSPy的新替代方案出现了,它以独特的LMP方法来解决问题。

DSPy是由斯坦福大学的研究人员创建的,旨在为不同的LMP任务提供改进的抽象。DSPy优先考虑编程而不是提示,旨在使基础能够创建更复杂的LMP应用程序。当前的LMP限制之一是它们在控制逻辑(如循环或条件语句)等任务上不太有效,而在任务如微调或知识增强等任务中,它们还需要基本不同的结构。DSPy试图通过以编程为中心的方法解决这些问题。

DSPy的经验和原则与深度学习领域的PyTorch有些相似。使用PyTorch构建深度学习应用程序时,数据科学家会建模给定的神经网络,并使用声明性层或优化器来融入所需的逻辑。类似地,DSPy包括像ChainOfThought或Retrieve这样的构建模块,并编译程序,根据特定的度量指标优化提示。虽然这在LMP中可能感觉像是一种新方法,但实际上这种方法是相当传统的。

DSPy

DSPy优先考虑编程而不是提示任务,统一了提示和微调语言模型(LMs)的策略。该框架通过推理和工具/检索增强增强了这些技术,所有这些技术都通过一组简洁的Python操作进行传达,这些操作是可组合和可学习的。

在DSPy的框架中,存在可组合和声明性的模块,旨在指导LLMs,并遵循熟悉的Python结构。值得注意的是,DSPy引入了一个自动编译器,教育LLMs执行程序中的声明性阶段。该编译器内部跟踪程序的执行,并随后设计适用于更大型LMs的高质量提示,甚至为较小的LMs训练自动微调,传授任务的复杂性知识。

DSPy作为涉及语言模型(LMs)和检索模型(RMs)的复杂任务的综合解决方案,统一了提示和微调LMs的方法,同时还适应了推理和工具/检索增强的方法。通过DSPy,这些方法被一组紧凑的Python模块封装起来,以实现组合性和学习性。

DSPy的框架通过提供可组合和声明性的模块,以Python用户熟悉的方式进行结构化。这种进步将“提示技术”(如思维链和自反思)从手动字符串操作策略提升到能够适应各种任务的多功能模块化程序。

值得注意的是,DSPy编译器在程序中的中间步骤不需要手动标签。这与传统的“提示工程”做法形成对比,后者依赖于临时的字符串操作技术。相反,DSPy打开了探索结构化领域的大门,其中包含了可组合和可训练的组件,提供了一种取代脆弱手动过程的系统方法。

DSPy编程体验基于两个基本构造:签名和电视提示器。

I. 签名:塑造LLM行为

在DSPy领域中,当任务分配给LM时,行为的具体性通过签名来表达。签名封装了与DSPy模块关联的输入/输出行为模式的声明性表示。

与引导LLM完成子任务相比,签名赋予DSPy用户阐明子任务的性质的能力。随后,DSPy编译器负责根据指定的签名、提供的数据和现有的流水线,为大型LM设计复杂的提示,或对较小的LLM进行微调。

一个签名由三个基本组成部分组成:

1)对LM所涉及子任务的简明描述。

2)对一个或多个输入字段(例如输入问题)的详细说明,这些字段将作为LM的输入。

3)对一个或多个预计由LM生成的输出字段(例如问题的答案)的解释。

以下代码示例展示了一个基于ChainOfThought模块的签名,其中包含了相当多的控制:

class GenerateSearchQuery(dspy.Signature):    """编写一个简单的搜索查询,用于回答一个复杂的问题。"""    context = dspy.InputField(desc="可能包含相关事实")    question = dspy.InputField()    query = dspy.OutputField()### 在程序的__init__函数中self.generate_answer = dspy.ChainOfThought(GenerateSearchQuery)

II. 通过dspy.teleprompt使程序优化成为可能。

编译是DSPy体验的核心。

编译依赖于三个关键因素:一个潜在紧凑的训练数据集,一个验证指标,以及从DSPy的库中选择一个电视提示器。这些嵌入在DSPy中的电视提示器是强大的优化器,能够掌握制定适用于任何程序模块的有影响力的提示的艺术。(“teleprompter”中的“tele-”前缀意味着“远程”,指的是提示的自动性质。)

值得注意的是,DSPy对标注的需求相对较低。以检索增强生成(RAG)流程为例:即使只有少数包含问题及其人工注释答案的实例,也足以满足要求。即使涵盖多个复杂的阶段,如包括上下文检索、思考链和最终答案的基本RAG模型,标签仅对初始查询和最终响应进行强制要求。DSPy能够巧妙地推断出支持整个流程所需的中间标签。如果对流程结构进行修改,引导数据将动态演化以适应修改后的设置。

RAG训练集的一个实例可以按如下方式组织:

my_rag_trainset = [  dspy.Example(    question="Gary Zukav的第一本书获得了哪个奖项?",    answer="国家图书奖"  ),  ...]

在此之后,明确验证标准是至关重要的。这个逻辑对程序行为或模块性能施加了约束。例如,RAG的验证函数可能包含如下检查:

def validate_context_and_answer(example, pred, trace=None):answer_match = example.answer.lower() == pred.answer.lower()context_match = any((pred.answer.lower() in c) for c in pred.context)return answer_match and context_match

不同的电视提示器选项在成本优化与质量增强方面存在不同的权衡。在RAG的背景下,一个选择可以是直接的BootstrapFewShot电视提示器。这涉及使用自定义验证函数(例如my_rag_validation_logic)初始化电视提示器本身,并随后针对指定的训练集(my_rag_trainset)进行编译。

from dspy.teleprompt import BootstrapFewShotteleprompter = BootstrapFewShot(metric=my_rag_validation_logic)compiled_rag = teleprompter.compile(RAG(), trainset=my_rag_trainset)

当使用编译后的RAG实例时,会引入一个阶段,即对带有复杂提示的LM进行调用。这些提示包括对链式思维检索增强型问答的简明演示,都针对当前使用的唯一数据集。

DSPy目前仍处于早期阶段,但已经展示出许多有前途的想法。简单而一致的编程模型类似于PyTorch的体验,以及模块化的体验使得LMP开发者能够构建相当复杂的应用。我希望DSPy能从这个初期阶段发展成一个可以与LangChain和LlamaIndex媲美的堆栈,因为该框架的许多思想在LMP领域中确实是必需的。

Leave a Reply

Your email address will not be published. Required fields are marked *