Created
Aug 14, 2024 01:47 PM
Favorite
Favorite
Priority
备注
推荐
🌟🌟🌟🌟🌟
类型
DSPy
点击上方蓝字关注我
本文:12000字阅读30分钟
亲爱的Prompt读者朋友们,这两天,我写了别再写脆弱的prompt讨好LLM啦!快用DSPy拯救你宝贵的prompt思维,偷偷甩掉99%的人,收到很多朋友的赞和在看,感谢你们!
今天给大家一个可以用到的Agent例子,和一个DSPy进行prompt优化的例子。
notion image
图片来自DALL.E
很多新手朋友运行DSPy都是倒在了安装和调试或者网络上,有了代码可能也很难跑出一个满意的结果。有几点苦涩的教训先分享给大家:
1、尽可能把DSPy的调试部署在Docker里,把CUDA的算力也指进来,同时打开每几秒监控的终端。
2、尽可能不用外网模型,开源模型尽量用正规大厂的,质量有保证。
3、代码尽可能在Jupyter Notebook上调试,虽然颜值没有VS code高,但调试还是比较方便。
4、不要给自己的能力设限,代码一遍报错多试几遍,总能Run出你满意的结果。
5、DSPy还在进步,封装的模块要尽可能的多了解它的能力边界。
以下是我目前正在使用DSPy里的模块,大家可以看一下
一、用dspy.ChainofThought实现一个简单的Agent
notion image
这段代码是使用 DSPy 框架创建一个简单的问答代理(agent),这个代理能够直接接收问题并使用配置好的语言模型来生成答案。下面逐步解释每一部分代码的功能和目的:
1. 配置语言模型
这行代码配置了 DSPy 框架使用的语言模型。这里的 `lm=llm` 指的是将 `llm`(一个已经初始化的语言模型)设置为当前环境的默认语言模型。这样,当你的代理或模块需要生成文本或进行预测时,它将默认使用这个模型。在你正确设置了模型之后,这些代码可以复现出上图的结果。
2. 定义一个简单的代理类
这里定义了一个名为 `SimpleAgent` 的类,它继承自`dspy.Module`。这是创建使用 DSPy 进行自定义处理的基本方式:
  • 构造函数 (`__init__`):在这里初始化模块。`super().__init__()` 调用父类的构造函数来正确设置模块。`self.answer_generator`是一个 `dspy.ChainOfThought` 对象,配置为接受一个问题并直接生成答案的文本。`dspy.ChainOfThought` 通常用于指导语言模型进行逻辑思考或连贯的推理以生成答案。
  • 前向传播方法 (`forward`):这是模块的核心方法,用于处理输入并返回输出。在这个方法中,`answer_generator` 直接使用传入的问题`question` 来生成答案。这种方式不涉及任何外部数据检索或复杂的逻辑处理,完全依赖于语言模型的能力来解释问题并生成相应的答案。
3. 实例化代理并使用
  • 实例化代理:创建 `SimpleAgent` 的一个实例,名为`simple_agent`。
  • 使用代理:使用这个代理来回答一个具体的问题:"How long does it take to fly from Beijing to New York with China Airlines?"。将问题作为参数传递给 `simple_agent` 的 `forward` 方法,并获取返回的答案。
  • 打印答案:输出答案的内容。这里假设 `answer_generator` 返回的对象有一个 `answer` 属性,这是生成的答案文本。
这段代码的核心是利用强大的语言模型直接生成答案,适用于那些不需要复杂数据检索或多步骤推理的场景。简单吧?用DSPy构造一个Agent有这么复杂吗?
二、进入深水区:DSPy Optimizers
上一篇文章里ICLR2024重磅 | DSPy或将手写Prompt推进历史,悄悄学会DSPy,一线技术圈很缺你这类人才我介绍了Metric(度量)和Assertions(断言),这一篇我们要详细介绍一下Optimizers,随着LLMs的引入,优化在机器学习系统中的作用发生了巨大的变化。LLMs不再需要梯度下降训练来提高特定任务的性能。相反,我们可以调整呈现给LLM的提示符的语言。提示调整有两个主要方面,说明和示例。
指令指的是通常放置在提示符开头的任务描述。不同的任务措辞方式将导致给定任务或语言模型的更好或更差的性能。例如,提示“写一个段落来回答这个问题”与优化过的提示不同:“分析给定的问题,识别其关键组成部分,并撰写一个结构良好,连贯的段落,彻底解决主要问题。”
通常我们只能靠勤劳的双手,手动优化提示是一项艰巨的任务,需要大量的试错和细微调整。幸运的是,DSPy为Prompt工程师带来了强大的Optimizers工具。
什么是DSPy Optimizers?
Optimizers是DSPy最强大的功能之一。详情您可以参阅:https://github.com/stanfordnlp/dspy/blob/main/docs/docs/building-blocks/6-optimizers.md
DSPy Optimizers是一组算法,可自动优化提示(prompts)和指令(instructions),以提高语言模型的性能。它们可以修改提示的结构、添加示例(demonstrations)或改变提示中的关键词,从而提高模型的输出质量。
DSPy提供了四种主要类型的Optimizers:
1). 自动Few-Shot优化(Automatic Fuse Shots)
2). 自动指令优化(Automatic Instruction Tuning)
3). 自动特征优化(Automatic Fine Tuning)
4). 程序转换优化(Program Transformation)
其中,自动Few-Shot优化是最常用和最有效的优化器之一。
1、自动Few-Shot优化(Automatic Fuse Shots)的奥秘
Few-Shot学习是一种有前景的技术,它通过向语言模型展示有限数量的示例,使其能够很好地推广到新的任务。自动Few-Shot优化就是利用这一思想,自动为语言模型生成和选择最佳的示例集。该优化器包含以下几个主要类:
  • LabeledFewShot:使用带标签的示例数据集,简单地从提供的标记Q/A对中构建几个示例
  • BootstrapFewShot:自动生成示例并从中选择最佳子集 ,使用您的程序为程序的每个阶段自行生成完整的演示。
  • BootstrapFewShotRandomSearch:对生成的演示进行多次随机搜索,并选择最佳方案。
  • BootstrappedFewShotOptuna:通过在演示集上优化Optuna超参数,运行试验以最大限度地提高评估指标。
2、指令优化(Automatic Instruction Tuning) 的力量
指令优化(Instruction Tuning)是另一种行之有效的优化方式。它通过优化提示中的关键词和指令,来提高语言模型的性能。
COPRO :为每一步生成和优化新的指令,并通过坐标提升优化它们。
MIPRO :在每个步骤中生成指令和少量示例。指令生成是数据感知和演示感知的。使用Bayesian Optimization来有效地搜索跨模块的生成指令/演示空间。
3、自动微调Automatic Finetuning
BootstrapFinetune:将基于DSP的程序提取为权重更新(适用于较小的LM)。输出是一个具有相同步骤的DSPy程序,但每个步骤都由微调模型而不是提示LM进行
4、程序变换Program Transformations
KNNFewShot:通过k-Nearest Neighbors算法集成BootstrapFewShot 进行自举/选择过程。
Ensemble:集成一组DSPy程序,并使用完整的程序集或随机抽取一个程序子集。
让我们通过一个实例来了解它清晰的流程,说明如何使用 BootstrapFewShot、COPRO 等优化器优化 RAG 管道,这个示例我可以通过这篇文章重磅 | DSPy让你不写一句Prompt照样构建Agent,从此,你不再卑躬屈膝讨好LLM的Dockerfile文件部署到本地,高级优化实例。
注意:示例只为说明流程,代码有删减 Weaviate 是一个向量数据库,也是和DSPy结合最紧密的数据库,在Docker里我已经部署了这个部分。
1. 设置环境
  • 连接本地 Weaviate 实例和其他所需工具,你都可以换成本地模型
  • 配置 DSPy 设置
2. 定义RAG 管道
  • 定义 `GenerateAnswer` 签名和 `RAG` 模块
  • 指定检索和生成组件
3. 准备数据集
  • 加载带有问题和黄金答案的数据集
  • 将数据集包装为 `dspy.Example` 对象
  • 分割为训练集、开发集和测试集
4. 定义评估指标
  • 定义 `TypedEvaluator` 签名
  • 实现 `MetricWrapper` 函数,用于评估预测答案与黄金答案的对齐程度
5. BootstrapFewShot 优化示例
  • 实例化 `BootstrapFewShot` 优化器
  • 使用 `compile` 方法生成最多 `max_bootstrapped_demos` 个高质量示例
  • 评估优化后的 RAG 管道性能
DSPy使用BootstrapFewShot 编译器进行编译。 BootstrapFewShot 通过程序生成跟踪,并将输出传递到度量中,以查看该示例是否值得作为输入—输出示例保留。这个指标可以是布尔值(true或false),也可以是数值,并与 metric_threshold 配对,以检查示例是否值得保留。事实上,这个演示中使用的训练数据集就是使用这个编译器创建的。
在BootstrapFewShot中添加随机搜索或Optuna
BootstrapFewShot 将停止搜索的例子,一旦它找到了 K 所需的数量的例子的提示;然而,这些可能不是最佳的 K 。
一种解决方案是使用DSPy的 BootstrapFewShotWithRandomSearch 或 BootstrapFewShotWithOptuna 。这些优化器不会生成所需的K并停止,而是生成 num_candidate 个示例并分别使用随机搜索或baking优化来找到要在提示中使用的 K 个示例的最佳集合。
随机搜索和贝叶斯优化是超参数调整的两种常用技术。随机搜索用于通过从生成的 num_candidate 示例中随机选择 K 示例并评估其性能来探索可能的示例组合的空间,最终找到提示的最佳示例集。
BootstrapFewShotWithOptuna 采用贝叶斯优化,它构建了所选示例与提示性能之间关系的概率模型,通过基于模型预测平衡探索和利用来指导搜索 K 示例的最佳集合。
6. COPRO 优化指令
  • 实例化 `COPRO` 优化器
  • 使用 `optimize` 方法生成候选指令集
  • 在训练集上评估每个候选指令,选择性能最佳的优化指令
  • 使用优化指令编译 RAG 管道并评估性能
DSPy有两个优化器来实现这一点:COPRO和MIPRO。这两种方法都使用 BasicGenerateInstruction 签名作为核心构建块:
COPRO首先生成具有 BasicGenerateInstruction 的breadth 指令候选。然后,通过在具有所提供的度量的训练集中运行每个候选指令来评估这些候选指令。然后将这些结果格式化为 GenerateInstructionGivenAttempts 以生成新指令。这继续进行 depth 轮以产生优化的指令。
7. 使用优化后的 RAG 管道
  • 在 Weaviate 的 `generative-search` 模块中使用优化后的指令和示例
  • 可选:将优化后的 RAG 管道保存为 JSON 文件以备将来使用
仔细体会这个流程,您可以充分利用 BootstrapFewShot、COPRO 和MIPRO 优化器的优势,从而显著提高语言模型在 RAG 任务上的性能。同时也要注意各种可能的注意事项和局限性。
我在群里为你准备了更多DSPy的示例,关于DSPy的问题你可以来群里问我。另外,群里为你准备了开群以来大量的Prompt模板、模块和一些代码文件完整示例,等你来一起讨论!另外,如果你有更多关于论文里Prompt的问题也可以到群里来,我会耐心解答你的问题。
notion image
<本文完结>
转载请与本喵联系,私自抓取转载将由律师维权AI已成为我洞察世界并输出想法的工具本地部署LLM成为你自己AI资源的掌控者
notion image
这份指南还包含8500条复杂Prompt,以及管理工具和方法(包含system提示词)
notion image
关于Prompt,这本手册,是你和我沟通的桥梁
notion image
🎉让我们一起创造更多美好!🎉
如果您觉得这篇文章对您有帮助或启发感谢您为我【点赞】【在看】
<您为我点赞在看,只有我能看到>
👉微信号:xiumaoprompt加我微信之前,请务必先点赞或在看这样我才能更快地识别并回应您
notion image
Loading...