DSPy:大模型应用编程框架入门与实践
DSPy 是斯坦福大学开发的用于构建基于语言模型应用程序的框架,旨在通过编程而非提示工程来解决应用脆弱性问题。它允许开发者定义签名和模块,并通过编译器自动优化提示或微调模型。文章介绍了 DSPy 的核心思想、工作流程、代码示例及其与 LangChain 的区别,展示了如何通过多跳问答任务演示其优化能力。

DSPy 是斯坦福大学开发的用于构建基于语言模型应用程序的框架,旨在通过编程而非提示工程来解决应用脆弱性问题。它允许开发者定义签名和模块,并通过编译器自动优化提示或微调模型。文章介绍了 DSPy 的核心思想、工作流程、代码示例及其与 LangChain 的区别,展示了如何通过多跳问答任务演示其优化能力。

随着大模型技术的普及和应用场景的扩展,开发者往往陷入无休止的 Prompt 调优中。市面上出现了提示词工程师这一角色,相关的技巧文章也层出不穷。然而,Prompt 工程在实际落地中面临诸多挑战。
虽然 Prompt 的技巧和调优效果明显,但没有任何一种策略能解决所有类型的问题。LLM 对提示词非常敏感,这意味着除了要求输出内容外,还需约束其格式、条件等以确保稳定性。一旦条件或数据微调,结果可能天差地别,需要重新调整 Prompt。
这引出了两个核心问题:
在此背景下,DSPy(Declarative Self-improving Language Model Programming)作为一种全新的 LLM 应用方式应运而生。它不讨论与 Prompt 工程的好坏,而是提供了一种系统化的构建方法。
DSPy 是斯坦福大学 NLP 研究人员开发的'基础模型编程'框架,旨在解决基于语言模型(LM)的应用程序脆弱性问题。它优先考虑编程而不是提示,允许您重新编译整个流水线,以便根据您的特定任务进行优化,而不是每当更改一个组件时重复人工提示工程。
DSPy 将程序的信息流与每一步的参数(提示和 LM 权重)分离开来,为构建基于 LM 的应用程序提供了更系统的方法。它将根据您的程序,自动优化如何针对您的特定任务提示(或微调)LM。
Signatures(签名):手动设计的提示 -> 用签名取代
告诉 DSPy 需要做什么,而不是如何做。例如:输入是文档,输出是摘要;输入是上下文 + 问题,输出是回复。
Modules(模块):提示技巧 -> 转变为模块化
在 DSPy 中是模块化组件,如
dspy.ChainOfThought、dspy.ProgramOfThought,类似于可调用的函数。
Optimizers(优化器):复杂的提示工程 -> 通过提词器和编译器自动完成
根据某个指标对整个流程自动优化。
使用 DSPy 构建基于 LM 的应用的工作流程与训练神经网络类似:
为了更直观地理解,我们以解决多跳问题为例,比如:'姚明的妻子的出生年龄?'这是一个典型的多跳问题,单轮搜索难以解决。大多数系统可以得出'姚明的妻子是谁',但无法回答后续年龄问题。使用 DSPy 只需几行代码即可实现并优化。
import dspy
turbo = dspy.OpenAI(model='gpt-3.5-turbo')
colbertv2 = dspy.ColBERTv2(url='http://20.102.90.50:2017/wiki17_abstracts')
dspy.settings.configure(lm=turbo, rm=colbertv2 )
多跳问题可以使用 HotPotQA 进行测试。
from dspy.datasets import HotPotQA
dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0)
trainset = [x.with_inputs('question') for x in dataset.train]
devset = [x.with_inputs('question') for x in dataset.dev]
print(len(trainset), len(devset))
# Output: (20, 50)
签名是最小形式的输入和输出字段的元组。与手写提示相比,签名可以通过引导示例编译成自完善和自适应管道的 prompt 或 fine-tune。
class GenerateAnswer(dspy.Signature):
context = dspy.InputField()
question = dspy.InputField()
answer = dspy.OutputField()
class GenerateSearchQuery(dspy.Signature):
context = dspy.InputField()
question = dspy.InputField()
query = dspy.OutputField()
DSPy 实现了多种 Module,包括 dspy.Predict、dspy.ChainOfThought、dspy.Retrieve 等。我们将签名传递给 ChainOfThought 模块,并使用输入字段的值进行调用。
以下是一个简化版的多跳检索生成器 SimplifiedBaleen 的实现:
from dsp.utils import deduplicate
class SimplifiedBaleen(dspy.Module):
def __init__(self, passages_per_hop=3, max_hops=2):
super().__init__()
self.generate_query = [dspy.ChainOfThought(GenerateSearchQuery) for _ in range(max_hops)]
self.retrieve = dspy.Retrieve(k=passages_per_hop)
self.generate_answer = dspy.ChainOfThought(GenerateAnswer)
self.max_hops = max_hops
def forward(self, question):
context = []
for hop in range(self.max_hops):
query = self.generate_query[hop](context=context, question=question).query
passages = self.retrieve(query).passages
context = deduplicate(context + passages)
pred = self.generate_answer(context=context, question=question)
return dspy.Prediction(context=context, answer=pred.answer)
my_question = "How many storeys are in the castle that David Gregory inherited?"
uncompiled_baleen = SimplifiedBaleen()
pred = uncompiled_baleen(my_question)
print(f"Question: {my_question}")
print(f"Predicted Answer: {pred.answer}")
print(f"Retrieved Contexts (truncated): {[c[:200] + '...' for c in pred.context]}")
可以使用打分来优化 DSPy 的结果。定义评估函数,检查预测答案是否相符、检索到的上下文是否包含真实答案、生成的搜索查询长度及重复率等。
def validate_context_and_answer_and_hops(example, pred, trace=None):
if not dspy.evaluate.answer_exact_match(example, pred): return False
if not dspy.evaluate.answer_passage_match(example, pred): return False
hops = [example.question] + [outputs.query for *_, outputs in trace if 'query' in outputs]
if max([len(h) for h in hops]) > 100: return False
if any(dspy.evaluate.answer_exact_match_str(hops[idx], hops[:idx], frac=0.8) for idx in range(2, len(hops))): return False
return True
使用 DSPy 中的 BootstrapFewShot 优化流程。DSPy 实现了多个提词器,如 LabeledFewShot、BootstrapFewShot、Ensemble 等,它们在优化成本和质量等方面提供不同的权衡。
from dspy.teleprompt import BootstrapFewShot
teleprompter = BootstrapFewShot(metric=validate_context_and_answer_and_hops)
compiled_baleen = teleprompter.compile(SimplifiedBaleen(), teacher=SimplifiedBaleen(passages_per_hop=2), trainset=trainset)
from dspy.evaluate.evaluate import Evaluate
def gold_passages_retrieved(example, pred, trace=None):
gold_titles = set(map(dspy.evaluate.normalize_text, example["gold_titles"]))
found_titles = set(
map(dspy.evaluate.normalize_text, [c.split(" | ")[0] for c in pred.context])
)
return gold_titles.issubset(found_titles)
evaluate_on_hotpotqa = Evaluate(devset=devset, num_threads=1, display_progress=True, display_table=5)
uncompiled_baleen_retrieval_score = evaluate_on_hotpotqa(uncompiled_baleen, metric=gold_passages_retrieved, display=False)
compiled_baleen_retrieval_score = evaluate_on_hotpotqa(compiled_baleen, metric=gold_passages_retrieved)
print(f"## Retrieval Score for uncompiled Baleen: {uncompiled_baleen_retrieval_score}")
print(f"## Retrieval Score for compiled Baleen: {compiled_baleen_retrieval_score}")
# Output:
# ## Retrieval Score for uncompiled Baleen: 36.0
# ## Retrieval Score for compiled Baleen: 60.0
LangChain、LlamaIndex 和 DSPy 都是帮助开发人员轻松构建基于 LM 应用的框架。使用 LangChain 和 LlamaIndex 的典型 pipeline 通常使用 prompt template 来实现,这使得整个 pipeline 对组件更改非常敏感。
相比之下,DSPy 将构建基于 LM 的管道从操作 prompt 转移到更贴近编程。DSPy 中新引入的编译器在更改基于 LM 的应用程序(如 LM 或数据)中的部件时,消除了任何额外的 Prompt 工程或微调工作。相反,开发人员可以简单地重新编译程序,以优化 pipeline 适应新添加的更改。因此,与 LangChain 或 LlamaIndex 相比,DSPy 可以帮助开发人员以更少的努力获得 pipeline 的性能。
本文回顾了 Prompt 使用过程中的痛点和问题,介绍了 DSPy 这一基于编程的大模型应用新范式。通过多跳问答任务的例子,展示了 DSPy 如何通过签名、模块和优化器自动构建和增强应用。目前生成式人工智能社区对该框架非常感兴趣,因为它将构建基于 LM 的应用程序从手动提示工程转向了可编程的自动化流程。
DSPy 的核心价值在于其声明式编程能力,使得开发者能够专注于任务逻辑而非底层提示细节,从而显著提升系统的稳定性和可维护性。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online