掘金 人工智能 09月22日
DSPy:声明式LLM应用开发新范式
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入介绍了DSPy,一个由斯坦福大学开发的LLM编程框架,它以声明式AI应用开发为核心理念,通过组合式Python代码而非过度依赖Prompt工程来构建AI应用。文章详细阐述了DSPy的四个核心模块:Signature(接口定义)、Module(逻辑封装)、Adapter(格式转换)和Optimizer(性能优化),并结合情感分析和猜名人游戏等实例,展示了如何利用DSPy实现复杂的LLM交互和优化。DSPy将LLM调用视为API调用,允许开发者定义输入输出格式,让LLM自适应,从而简化了开发流程,提高了模型的可控性和稳定性。

🌟 **DSPy的声明式开发范式**:DSPy框架的核心在于其声明式编程理念,它允许开发者通过编写组合式的Python代码来定义AI应用的逻辑,并将LLM调用视为API调用。这种方式减少了对繁琐Prompt工程的依赖,使开发者能够专注于应用本身的逻辑,而不是受限于LLM的特定指令格式。通过预先定义输入输出格式,DSPy使得LLM能够自适应开发者的需求,从而简化了构建和维护AI应用的过程。

⚙️ **四大核心模块助力高效开发**:DSPy由Signature、Module、Adapter和Optimizer四个核心模块构成。Signature负责明确定义LLM交互的输入输出格式;Module用于封装业务逻辑,可以将多个Signature组合成复杂的推理流程;Adapter负责在Signature和LLM之间进行格式转换,将LLM响应解析为结构化数据;Optimizer则通过智能搜索和评估,自动优化Prompt模板和few-shot示例,显著提升程序性能。这四大模块协同工作,为开发者提供了一个强大而灵活的开发环境。

💡 **实际应用案例展示**:文章通过情感分析和猜名人游戏两个具体案例,生动地展示了DSPy的应用。在情感分析场景中,DSPy能够清晰地定义输入文本和输出情感分数,并可选择性地生成推理过程。在猜名人游戏场景中,DSPy通过多轮对话和分层推理,能够有效地管理历史对话信息,并根据上下文进行智能提问和猜测,最多可支持20次提问机会。这些案例直观地体现了DSPy在处理复杂LLM任务时的强大能力和易用性。

🚀 **性能优化与自动化**:DSPy的Optimizer模块为AI应用的性能优化提供了自动化解决方案。通过MIPRO V2等优化器,DSPy能够自动搜索和评估最优的Prompt模板和few-shot示例组合,从而显著提升模型的准确性和效率。开发者可以根据需求选择不同的优化模式(如light、medium、heavy),或者通过自定义评估指标和示例数量来精细控制优化过程,最终获得经过优化的、性能卓越的DSPy程序。

本文较长,建议点赞收藏。更多AI大模型应用开发学习视频及资料,在智泊AI

🌟 DSPy项目背景

DSPy 是斯坦福大学开发的LLM编程框架,在GitHub上已获得27.5k+ stars
代表着声明式AI应用开发的新范式。其核心理念是通过编写组合式Python代码,而不过度依赖Prompt工程。

项目地址:
github.com/stanfordnlp…

从问题开始

假如让你构建一个AI应用,任务是对用户评论进行情感分析。使用提示词Prompt的方式下,你会怎么做?

prompt"请分析以下文本的情感,返回0-10的分数,数字越大表示越积极:{text}"response = llm.generate(prompt.format(text="我很开心!"))

但这种方式存在什么问题?当提示内容复杂的时候,每次调整都需要重写Prompt。当面对不同任务时,都要重新设计Prompt。当模型更换时,可能还需要重新调试Prompt。

那同样的任务,通过Dspy是怎么解决的?Dspy的核心是:通过在客户端声明数据格式,将LLM调用看作是API调用。

这里的关键是声明式,首先要理解传统的API的调用方式,通常由服务端预先定义好接口格式,然后客户端必须按照服务端的规范发送请求,数据格式是"服务端主导"的,服务端说什么格式,客户端就必须用什么格式。举个例子,服务端按下面定义,那么客户端传参数时,必须传city、date。:

response = requests.post('/api/weather', {    'city''北京',            'date''2025-08-23'          # 必须按服务端要求})temp = response['temperature']  # 服务端决定返回什么字段

而Dspy是客户端(代码)定义输入输出格式,服务端LLM去自适应,是声明式的开发方式。

# DSPy:LLM适应你定义的格式class WeatherQuery(dspy.Signature):    city = dspy.InputField()           # 输入city    temperature = dspy.OutputField()          # 输出温度

这样做的好处是,不必要跟随着LLM的响应结果走了。传统API固定了响应格式,当LLM输出格式不稳定时,还需要兼容修改解析代码,影响解析结果。

Dspy实现机制-四个核心模块

这里用情感分析的例子来贯穿这四个核心模块。

Signature:接口定义模块

Signature负责显式定义LLM交互的输入输出格式,使得模型响应无需手动解析字段,确保每次LLM调用都有明确的共识。根据应用复杂度的不同,DSPy提供了两种Signature定义方式:

方式一:类基签名(适用于复杂任务)

当需要精确控制字段类型、描述和约束时,推荐使用类基签名。它通过继承 dspy.Signature 类实现,包含 五个核心组件 :

class SentimentClassifier(dspy.Signature):    """对给定文本进行情感分类."""    text: str = dspy.InputField(desc="需要分析情感的输入文本")    sentiment: int = dspy.OutputField(        desc="情感分数,数值越高表示越积极正面,范围0-10",        choices=[012345678910]    )

方式二:字符串基签名(适用于快速原型)

当需要快速实验和原型开发时,可直接使用字符串签名:

# 字符串基签名示例classify = dspy.Predict("text -> sentiment: int")

Module:逻辑封装模块

Module负责封装与LLM交互的业务逻辑。当通过Signature定义好输入输出接口后,Module将这些接口组织成可执行的推理流程,把多个Signature组合成复杂推理链,再通过forward()方法管理复杂的业务逻辑执行。根据应用复杂度的不同,DSPy提供了两种Module使用方式:

方式一:直接使用内置Module(适用于简单任务)

当任务相对简单时,可以直接使用DSPy提供的内置模块:

# 使用内置模块的情感分析示例classify = dspy.Predict(SentimentClassifier)result = classify(text="我很开心!")

方式二:自定义Module(适用于复杂应用)

当需要构建复杂的多步骤推理流程时,需要继承 dspy.Module 并自定义逻辑:

# 自定义模块示例class CelebrityGuess(dspy.Module):    def __init__(self):        self.question_generator = dspy.ChainOfThought(QuestionGenerator)        self.reflection = dspy.ChainOfThought(Reflection)        def forward(self, celebrity_name):        # 复杂的多轮对话逻辑        # ...

Adapter:格式转换模块

Adapter负责在Signature和LLM之间进行格式转换。当通过Signature定义好输入输出接口后,Adapter将这些接口转换成LLM能理解的prompt格式,并将LLM的文本响应解析为结构化数据,实现将语言模型当作"有明确定义输入输出的API"来使用的目标。根据转换复杂度的不同,DSPy提供了两种Adapter使用方式:

方式一:自动选择Adapter(适用于大多数场景)

当使用DSPy的内置模块时,框架会自动选择合适的Adapter:

# 自动选择Adapter的情感分析示例classify = dspy.Predict(SentimentClassifier)result = classify(text="我很开心!")# Adapter自动处理prompt构建和响应解析print(result.sentiment)  # 直接访问结构化结果

方式二:自定义Adapter

当需要特定的prompt格式或解析逻辑时,可以自定义Adapter:

# 配置自定义Adapter示例dspy.settings.configure(    lm=dspy.LM("openai/gpt-4o-mini"),    adapter=CustomAdapter()  # 使用自定义适配器)

实际执行流程(隐式)

Adapter配置完成后,运行时实际的工作流程主要有三步(隐式实现):接受输入->构建prompt->解析响应

      接收三类输入:Signature(签名定义)、User input(用户输入)、Module info(模块信息)
      构建结构化prompt
      解析LLM响应

可以通过dspy.inspect_history()查看Adapter的完整工作过程:

# LLM的原始输出"""[[ ## reasoning ## ]]The text "我很开心!" expresses a clear positive emotion with the word "开心" (happy). The exclamation mark further emphasizes the positive sentiment.[[ ## sentiment ## ]]9"""# Adapter解析后的结构化结果result.reasoning = "'The text "我很开心!" expresses a clear positive emotion with the word "开心" (happy). The exclamation mark further emphasizes the positive sentiment.'"result.sentiment = 9  # 自动转换为int类型

注意:使用dspy.ChainOfThought才会包含推理过程,直接使用dspy.Predict不会显示推理过程(也就是reasoning),而是直接输出结果。

Optimizer:性能优化模块

Optimizer负责自动优化DSPy程序的性能,解决传统手工调试prompt的痛点。当构建好Module和Signature后,Optimizer通过智能搜索和评估,自动找到最优的prompt模板和few-shot示例组合,实现程序质量的显著提升。根据优化需求的不同,DSPy提供了两种Optimizer使用方式:

方式一:自动模式优化(适用于大多数场景)

当需要快速获得优化效果时,可以使用DSPy提供的自动模式:

# 使用自动模式的优化示例optimizer = dspy.MIPROv2(mode="auto")  # 可选:light, medium, heavyoptimized_program = optimizer.compile(    student=program,    trainset=train_data,    valset=val_data,    metric=accuracy_metric)

这里的program 就是你自己构建的 DSPy 模块实例 。可以是:dspy.Predictdspy.ChainOfThought、 dspy.ReAct或者自定义模块。train_data是你用来优化的数据集,类似HotPotQA所使用的QA数据集。Optimizer会用这些数据来生成 few-shot 示例(通过 bootstrapping 过程),选择最佳的指令和示例组合。

# HotPotQA数据集示例train_data = [    {        "question""Which magazine was started first Arthur's Magazine or First for Women?",        "answer""Arthur's Magazine"    },    # ... 更多训练样本]

方式二:自定义优化

当需要精细控制优化过程时,可以自定义优化器配置:

# 自定义优化示例defcustom_metric(example, prediction):    return example.answer == prediction.answer# custom_metric: 使用什么评估指标# max_bootstrapped_demos: 最多生成多少个bootstrap示例# max_labeled_demos: 最多使用多少个标注示例optimizer = dspy.BootstrapFewShot(    metric=custom_metric,    max_bootstrapped_demos=8,    max_labeled_demos=4)optimized_program = optimizer.compile(    student=program,    trainset=train_data)

实际执行流程(隐式)

当调用ptimizer.compile() ,DSPy 实际会执行四步流程:

      构建few-shot示例集:方式是通过bootstrapping,从训练数据中取样本,输入DSPy程序执行,记录完整的执行过程,使用度量函数评估输出质量,当得分超过设定阈值时,提取该过程中每个模块的输入-输出对,作为该模块未来的few-shot示例候选;
      生成指令候选:收集功能描述、few-shot示例和风格提示等信息,将它们组合成结构化输入,发送给DSPy proposer(指令生成器),该组件基于这些信息生成多个针对特定模块的指令候选,为后续的优化过程提供更多指令选择;
      智能组合评估:使用贝叶斯抽样方法从few-shot示例集和指令候选集中智能选择组合,构建候选程序并进行评估。评估过程基于用户定义的度量函数和验证数据集,通过将程序输出与标准答案进行比较来计算得分;
      选择最优配置:最终选择得分最高的候选程序作为优化后的最终配置;

案例一-情感分析实现

需求描述

构建一个情感分析系统,要求:

代码实现

结合前面提到的四个模块,可以很容易的实现:

案例二-猜人名游戏多轮对话

需求描述

构建一个"猜名人"游戏AI代理:

设计思路

1. 多轮对话

首先思考多轮对话的设计实现,既然是多轮对话,就要包含历史对话的内容信息。没有历史感知的方式,是每次都重新开始,例如:

# 每轮独立,历史容易丢失for attempt in range(20):    question = generate_question()  # 从零开始,无历史感知    answer = get_user_input()

使用dspy要传入完整的历史,每次的决策都是基于全局的上下文:

# 每轮都是基于完整历史的智能决策for attempt in range(20):    question_result = self.question_generator(        past_questions="\n".join(past_questions),  # 传入完整历史        past_answers="\n".join(past_answers)       # 传入完整历史    )    # 新的交互立即成为下一轮的历史    past_questions.append(question_result.new_question)    past_answers.append(answer)

2. 分层推理-ChainOfThought的reasoning

要想回答正确,需要从宽泛的问题逐步缩小范围到具体答案。通过reasoning和历史上下文,由AI自动来做分层推理。

3. 判断推理成功

设置guess_made,当AI认为有足够的信息可以推断时,guess_made=True时,AI认为信息足够,开始直接猜测。当guess_made=False时,AI生成宽泛的分类问题继续提问。

class QuestionGenerator(dspy.Signature):    """Generate a yes/no question to narrow down the celebrity guess."""    past_questions: str = dspy.InputField(desc="previously asked questions")    past_answers: str = dspy.InputField(desc="corresponding yes/no answers")    new_question: str = dspy.OutputField(desc="new yes/no question to ask")    guess_made: bool = dspy.OutputField(desc="whether this is a direct guess"

代码实现

定义子模块Signature:

控制流程模块:

游戏演示:

运行结果:

学习资源推荐

如果你想更深入地学习大模型,以下是一些非常有价值的学习资源,这些资源将帮助你从不同角度学习大模型,提升你的实践能力。

本文较长,建议点赞收藏。更多AI大模型应用开发学习视频及资料,在智泊AI

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

DSPy LLM AI开发 声明式编程 Prompt工程 自然语言处理 机器学习 Stanford University DSPy framework Declarative AI Natural Language Processing Machine Learning AI Development Programming Framework
相关文章