首页 > 其他分享 >DSPy:提示词工程师的“终章”?

DSPy:提示词工程师的“终章”?

时间:2024-07-21 09:25:53浏览次数:14  
标签:工程师 提示 模型 模块 终章 DSPy 优化 dspy

作者:老余捞鱼

原创不易,转载请标明出处及原作者。

写在前面的话:
伴随 AI 应用的广泛推广与普及,人们逐渐意识到,提示词工程绝非万能的艺术抑或科学,它并非对所有问题的提示策略都行之有效,只有部分提示语在孤立情形下看似优良,然而在综合运用时却难担重任。并且,每当大模型平台的某个版本进行升级后,原先有效的提示词失效的情况屡见不鲜。正因如此,提示词工程师似乎愈发与数据标注员的工作性质趋同,需要进行大量的重复操作、反复试验以及手工制作,高价值的产出日益减少,陷入了尴尬之境,同时这也并非能够可持续构建出优质应用的有效方法。好在DSPy 的出现为化解此难题开辟了一条崭新的路径。

一、提示工程存在的问题

       我清晰地记得就在几个月之前,提示工程还是个热门话题,而且整个就业市场都遍布着招聘提示词工程师的身影。然而现今在硅谷,情况似乎并非如此。AI 从业公司已普遍意识到,提示词工程并非什么艺术或者科学,它仅仅是一种精妙的汉斯现象(是指在某些情况下,人们错误地将简单的关联或巧合视为具有某种深刻含义或规律的现象),提示词工程是人类为AI提供必要的上下文,使系统能以更优的方式给出回答。人们甚至还撰写了一些书籍/博客,诸如《人人都是提示工程师》之类的。

       随着大规模的应用已明确表明,提示词工程并不适用于所有问题的单一提示语或提示策略,只是有部分提示语在孤立的状态下看似更好,可在综合分析时却不堪重用。而当大模型平台的某个版本升级后,原来的提示词无效的例子比比皆是。所以就造成了提示词工程师看上去越来越和数据标注员这个工种的工作性质类似,需要大量重复、反复试验手工制作,高价值产出物在不断减少的尴尬境地,同时这也不是能可持续构建出一个好应用的方法。而DSPy的出现为破解这个问题探索出一条新的道路。

进一步理解提示工程存在的问题

        举例来说,当我说“Add 5-shot CoT with RAG, using hard negative examples”,这句话在概念上是不是非常清晰?但在具体到提示词实践中却很难实现,因为LLM 对提示非常敏感,所以在提示中加入这种结构在大多数情况下是行不通的。同时LLM 的行为对提示语的编写方式非常敏感,照成了在这种情况下很难引导它们。因此,当我们构建管道时,不仅仅是提示词工程师要说服 LLM 以某种方式提供输出,更多的输出应该受到限制,使其可以作为管道中其他模块的输入。

       为了解决这个问题,目前已经有很多研究在进行,但取得突破性进展的不多,大多数研究都致力于字符串模板,但这种模板既脆弱又不可扩展。随着时间的推移,语言模型会发生变化,提示也会随之中断。如果我们想将我们的模块插入不同的管道,它就会失效。我们想让它与更新的工具、新的数据库或检索器交互,它也无法工作。而这正是 DSPy 所要解决的问题,它将 LLM 视为一个模块,根据它与管道中其他组件的交互方式自动调整其行为。

二、DSPy 介绍

        DSPy(“Declarative Self-Improved Language Programs (in Python)”,发音为“dee-es-pie”)是一个由斯坦福大学 NLP 研究人员开发的“基于基础模型的编程”框架。提供开源供大家一起来研究使用, GitHub 页面(GitHub - stanfordnlp/dspy: DSPy: The framework for programming—not prompting—foundation models )。

        正如我前文描述所述,使用大型语言模型构建应用程序通常较为复杂且脆弱,因为其典型的流程常使用通过反复试验手工制作的提示语来实现,而语言模型对提示方式很敏感,当更改流程中的部分组件(如语言模型或数据)时,可能会影响性能,除非调整提示或进行微调步骤。DSPy 旨在解决基于语言模型的应用程序中的脆弱性问题,它强调编程而非提示,通过将程序的信息流与每个步骤的参数(如提示和语言模型权重)分离,为构建基于语言模型的应用程序提供了更系统化的方法。该框架引入了一系列概念,用签名抽象并替换手写的提示和微调,用模块抽象并替换更高级的提示技术,同时通过提示器和编译器将手动提示工程自动化。

        与其他一些框架相比,使用 LangChain 和 LlamaIndex 的典型流程通常使用提示模板实现,这使得整个流程对组件变化非常敏感。而 DSPy 中引入的编译器在改变基于语言模型应用程序中的组件(如语言模型或数据)时,消除了额外的提示工程或微调工作,开发人员只需重新编译程序,即可优化流程以适应新的变化,从而能以更少的工作量获得较好的流程性能。此外,对于有数据科学背景的人来说,DSPy 的语法与 PyTorch 有相似之处,例如在 PyTorch 中通用层可在任何模型架构中组合,在 DSPy 中通用模块可在任何基于语言模型的应用程序中组合,编译 DSPy 程序类似于在 PyTorch 中训练神经网络(其中使用优化器训练模型权重)。因此,DSPy 的目标是将重点从调整 LLM 转移到良好的总体系统设计上。

但如何做到这一点呢?
        从思维层面思考这个问题,我们可以将 LLMs 视为 设备:执行指令并通过类似 DNN 的抽象方法进行操作。例如,我们在 PyTorch 中定义了一个卷积层,它可以对来自其他层的一组输入进行操作。从概念上讲,我们可以堆叠这些层,并在原始输入上实现所需的抽象级别,我们不需要定义任何 CUDA 内核和许多其他指令。所有这些都已在卷积层的定义中进行了抽象。这就是我们希望通过 LLMs 实现的效果,LLMs 是抽象化的模块,通过不同的组合堆叠来实现某种行为,无论是 CoT、ReAct 还是其他。

三、如何用 DSPy 进行模型训练

        为了实现所需的行为,我们需要用 DSPy 进行模型训练。使用 DSPy 构建基于语言模型的工作流程如下:首先收集数据集,即收集程序输入和输出的一些示例(如问题和答案对),用于优化流程;然后编写 DSPy 程序,使用签名和模块定义程序逻辑以及组件之间的信息流来解决任务;接着定义验证逻辑,即使用验证度量和优化器(提示器)来优化程序;之后编译 DSPy 程序,编译器会将训练数据、程序、优化器和验证度量等都考虑在内,以优化程序(例如提示或微调);最后进行迭代,通过改进数据、程序或验证等,重复这个过程,直至对流程的性能满意为止。我下面用python一步步的演示给大家看:

1. 配置语言模型:使用 dspy.openai 函数配置所需的语言模型,例如指定模型名称(如性价比最高的gpt-4o-mini)和 API 密钥。

import dspy llm = dspy.openai(model='gpt-4o-mini-2024-07-18', api_key=your_openai_api_key) dspy.settings.configure(lm=llm)

2.定义任务签名:任务签名用于描述输入和输出的格式。可以创建一个自定义的签名类,明确输入字段和输出字段的描述。

class your_signature(dspy.signature): """任务的具体描述""" input_field = dspy.inputfield(desc="输入字段的描述") output_field = dspy.outputfield(desc="输出字段的描述")

3.创建模块:基于定义的签名创建相应的模块,模块将使用签名来执行具体的任务。

class your_module(dspy.module): def forward(self, *inputs): # 在此处实现模块的具体逻辑 # 使用语言模型进行处理并返回输出 return output

4.生成合成数据(可选):如果数据稀缺,可以使用其他方法(如结合 LangChain)生成合成数据,以便更好地进行提示优化。例如,使用 LangChain 根据预设的标准或结构生成具有真实数据特征的结构化输出。


5.进行提示优化(如果需要):利用 DSPy 的提示优化功能,根据合成数据或已有数据来优化提示。可以使用 bootstrap_fewshot 等方法进行优化。


6.定义训练集:如果需要训练模型,将合成数据或实际数据转换为适合训练的格式。例如,将数据与定义的签名进行关联,为模块提供输入。

train_set = (x.with_inputs('input_field_name') for x in few_shot_examples)

7.使用模块进行推理或训练:在训练或推理阶段,调用模块的方法并传入相应的输入数据,获取模型的输出。

module = your_module() response = module(input_data)

8.编译和优化(可选):使用 DSPy 编译器对整个流程进行编译和优化,编译器会考虑程序、训练数据、验证指标等,自动生成优化的调用策略和提示(或微调模型)。

from dspy.teleprompt import bootstrap_fewshot from dspy.evaluate import answer_exact_match # 进行编译和优化的代码示例 compiler_optimized_module = bootstrap_fewshot(module, train_set) response = compiler_optimized_module(input_data)

9.迭代和改进:根据模型的输出结果和性能评估,不断改进数据、程序或验证逻辑,重复上述步骤进行迭代,以提高模型的性能。

       这只是一个基本的概述,实际使用 DSPy 进行模型训练时,需要根据具体的任务和需求来详细设计签名、模块以及优化策略。同时,还需要根据数据的特点和问题的复杂性进行调整和扩展。

       请注意,确保已经正确安装了 DSPy 及其所需的依赖项。此外,不同的任务可能需要不同的签名、模块和优化方法,具体的实现会因问题而异。建议参考 DSPy 的文档、示例代码以及相关的教程,以便更好地理解和应用于特定的场景。

        以下是一个简单的示例代码,展示了使用 DSPy 进行谎言检测的基本步骤,包括定义签名、生成合成数据和进行提示优化:

import dspy 
from typing import List 
from langchain.prompts import prompt_template 
from langchain_core.output_parsers import json_output_parser 
from langchain_core.pydantic_v1 import BaseModel, Field 
from langchain_openai import ChatOpenAI 

# 配置语言模型 
llm = ChatOpenAI(temperature=1, api_key=your_openai_api_key) dspy.settings.configure(lm=llm) 

# 定义谎言检测的签名 
class Veracity(dspy.signature): 
"""评估一个陈述的真实性""" 
fact = dspy.inputfield(desc="一个陈述") 
answer = dspy.outputfield(desc="对陈述真实性的评估")

class LieDetector(dspy.module): 
def forward(self, fact):
# 这里可以添加具体的处理逻辑,使用语言模型进行判断等 
return {"answer": True} # 假设简单地返回 True 作为示例 

# 生成合成数据 
class Data(BaseModel): 
fact: str = Field(description="关于生活、科学或历史的一般事实") 
answer: str = Field(description="事实的真实性,布尔值 1 或 0") 

parser = json_output_parser(pydantic_object=Data) 
prompt = prompt_template( template="回答用户查询\n{format_instructions}\n{query}\n", 
input_variables=("query"), 
partial_variables={"format_instructions": parser.get_format_instructions()} ) 
chain = prompt | model | parser 

list_of_facts = (chain.invoke({"query": "生成数据"}) for _ in range(10)) # 生成 10 个事实-答案对 few_shot_examples = (dspy.example(fact) for fact in list_of_facts) 

# 合成提示优化 
from dspy.teleprompt import bootstrap_fewshot 

# 将事实定义为谎言检测器的输入 
train_set = (x.with_inputs('fact') for x in few_shot_examples) 

# 优化谎言检测器模块 
compiled_lie_detector = bootstrap_fewshot(LieDetector(), train_set) 

# 进行谎言检测 
text = "月亮是由奶酪组成的" 
response = compiled_lie_detector(fact=text) 
print(response.answer)

        在上述示例中,首先定义了一个用于谎言检测的签名 Veracity,其中包含输入字段 fact(待检测的陈述)和输出字段 answer(真实性评估)。然后创建了一个简单的 LieDetector 模块,其 forward 方法目前只是简单地返回 True 作为示例。

       通过生成合成数据,使用 LangChain 生成了一些带有事实和真实性答案的示例数据。接着,使用 bootstrap_fewshot 函数对 LieDetector 模块进行了提示优化,得到优化后的 compiled_lie_detector

       最后,使用优化后的模块对一个示例文本进行谎言检测,并打印出结果。

       请注意,这只是一个简单的示例,实际应用中可能需要更复杂的模块逻辑和更全面的优化策略,具体取决于你的任务需求和数据特点。同时,还需要根据实际情况调整签名、模块的定义以及生成合成数据的方式等。此外,确保将 your_openai_api_key 替换为你实际的 OpenAI API 密钥。

       上图是DSPy为了可视化优化过程中的进度,通过检查正在优化的提示、签名和演示、正在评估的示例以及 LM 调用和成本来帮助理解和调试优化器:DSPy Visualizer

       如果你想详细了解 DSPy,可以访问其 GitHub 页面获取更多信息。(GitHub - stanfordnlp/dspy: DSPy: The framework for programming—not prompting—foundation models )

四、结论

       很多现实结果都表明,在 DSPy 中结合多跳设置甚至可以超越人工反馈。甚至在 DSPy 设置中尝试使用 T5 等更小的模型也能与 GPT 相比。在 lang chain 发布后,DSPy 是我遇到过的最酷的系统之一,这表明我们有希望制造出更好的、系统化设计的系统,而不是在大型 LLM 管道中胡乱拼凑。最后,如果这篇文章对您有价值,请为我点赞。


本文内容仅限制用于技术探讨和学习,原创不易,转载请标明出处及原作者。

标签:工程师,提示,模型,模块,终章,DSPy,优化,dspy
From: https://blog.csdn.net/weixin_70955880/article/details/140568815

相关文章

  • 后台前端工程师
     后端开发接触前端开发的程序员,可以成为全栈工程师。前端也可以写后台,学习的知识技能要更多。后台工程师的分量更重,前端更轻。JavaScript是动态弱类型语言,没有强制的类型检查,错误校验之类的。现比较智能的IDE工具支持JavaScript的编写,不能很好地进行调试编译。Java后......
  • 测试工程师在敏捷项目中扮演什么角色?
    敏捷团队中的测试人员主要负责执行各种测试,以满足“已完成”的定义,从而为团队在重复迭代中努力交付的持续价值创造做出贡献。对于测试人员来说,拥有敏捷的心态是至关重要的,如果没有敏捷的思维方式,他们可能就不能果断地计划、划分优先级并执行他们的任务,因此会无意中影响团队满足迭......
  • 【新手硬件工程师学习日记】之电容的九大作用
    1、隔直流隔直流电容作用:阻止直流通过而让交流通过。2、旁路(去耦)高频旁路电容器作用:为交流电路中某些并联的组件提供低阻抗通路。3、耦合耦合电容电路模型作用:作为两个电路之间的连接,允许交流信号通过并传输到下一级电路。......
  • 电路仿真软件使用七大技巧,让你秒变电子工程师!
    在电子工程领域,电路仿真软件无疑是工程师们不可或缺的工具。但是,你是否已经充分掌握了这些软件的使用技巧,让它们在项目中发挥最大效能呢?今天,就让我们一起来揭秘电路仿真软件使用的七大技巧,助你秒变电子工程师!一、选择合适的仿真软件首先,我们要明确自己的需求和目标。不同的电......
  • 快速入门:自动驾驶感知工程师的规划与决策核心技巧
    亚马逊云AWS大模型训练自动驾驶技术欢迎来到雲闪世界,亚马逊AWS雲服务器。经典的模块化自动驾驶系统通常由感知、预测、规划和控制组成。直到2023年左右,AI(人工智能)或ML(机器学习)主要在大多数量产自动驾驶系统中增强感知,其影响力在下游组件中逐渐减弱。与规划堆栈中AI的......
  • 解锁网络无限可能:揭秘微软工程师力作——付费代理IP池深度改造与实战部署指南
    基于付费代理的代理IP池项目来源此项目为微软某个工程师构建的代理IP池,我对此进行了改造。可以用于生产环境中的爬虫项目阅读前建议阅读我之前发布的爬虫基础的文章,了解代理如何获取、使用等。分为四大模块代理生成基于购买的付费代理接口获取代理IP,利用redis数据库的有......
  • 如何与 LLMs 有效沟通?6位数提示词工程师经验(LLMs 提示词小白必学)
    除非你活在太空里,完全脱离了现代社交媒体和新闻的关注,否则你不太可能错过大型语言模型    欢迎来到云闪世界。除非你活在太空里,完全脱离了现代社交媒体和新闻的关注,否则你不太可能错过大型语言模型(LLM)的突飞猛进带给我们生活中的革命性进步。LLM的演变。......
  • 分享 LLM 大语言模型算法特训 带你转型 AI 大语言模型算法工程师
    摘要本文旨在探讨大型语言模型(LargeLanguageModel,LLM)的进化路线,重点分析其领域微调技术的发展以及这些模型在自然语言处理(NaturalLanguageProcessing,NLP)中的应用范式。通过文献综述、技术分析和案例研究,本文详细阐述了LLM如何从统计语言模型发展到基于Transform......
  • 面试安全工程师
    简介:这是我大三下准备实习面试的一家北京的信息安全公司,本次面试为线上面试,技术和HR一起参与面试。已拿offer1、对称加密和非对称加密的区别对称加密的特性1.单钥密码系统对称加密采用单钥密码系统,即加密和解密使用相同的密钥。这意味着信息的发送方和接收方必须共享一个......
  • 网络安全工程师入门,看这一篇就够了!
    前言众所周知,为了能够有效地应对黑客袭击,保障网络安全,国家大大加强了对网安方面人才建设的培养。网络安全相关岗位的薪酬非常高,相关证书的补贴也很多,因此学习网络安全、转行网络安全的人可谓是“蜂拥而至”。网络安全不缺人,但缺人才。很多对网络安全感兴趣的朋友,总是在寻......