微软SAMMO vs 传统方法:结构化Prompt压缩效率测评
大语言模型持续进化,其处理输入的长度与复杂程度不断突破。这为设计复杂提示词(Prompt)打开了更大的空间——但要让这些提示词在生产部署中稳定输出理想结果,通常还需要反复调校。
市面上已有多种自动化Prompt优化工具,但随着提示词自身复杂度的攀升,许多传统方法逐渐显露局限。核心痛点在于:我们需要一种全新的思路来优化这种“元提示程序”(Metaprompt)。正是基于这一目标,微软研究院提出了SAMMO框架,全称为“结构感知多任务元提示优化”(Structure-Aware Multi-objective Metaprompt Optimization)。其核心价值在于:实现了对Metaprompt的“编译时优化”。
标题:作为程序的Prompt:一种结构感知的高效提示优化方法
论文地址:https://arxiv.org/pdf/2404.02319.pdf
SAMMO的独特之处在于,它不再将Prompt视作单纯的文本,而是将其当作一个结构化对象。这样一来,优化过程便能在更丰富的“变换集”中高效搜索。相较于以往的自动化Prompt优化方法,SAMMO具备五个直观优势:
1. 高效的数据标签:将多个数据点打包到单个提示符中并解析,大幅降低标注成本。
2. 提示原型与工程:将Prompt表示为有向无环图,组件可复用、结构易调整,快速搭建和迭代新提示变得十分高效。
3. 指令优化:利用结构化表达能力优化指令,在特定任务上显著提升性能。
4. 提示压缩:在保持性能的前提下,大幅压缩提示的长度与复杂度,降低计算开销。
5. 大规模快速执行:支持并行与速率限制,能同时发起大量查询,避免LLM API过载。
SAMMO工作原理
SAMMO的核心思路非常直接:将Prompt表示为一个结构化程序——一个有向无环的函数图G。在该图中,SAMMO定义了一系列“结构感知的Prompt变异算子”,包括重排节点、替换节点、删除节点,以及修改节点参数等。每个节点v都带有自己的函数类型ψ_v和静态参数θ_v,分别对应Prompt的不同部分,如任务描述、指南、示例或输入输出格式。节点之间的有向边e_ij定义了父子关系:父节点可接收子节点传来的动态输入X和消息。
整个Prompt程序π*由递归求值该函数图得到:
π[X] = ψ_vr(X ∪ ψ_children) θ_vr)
其中vr为根节点,ψ_children是从子节点汇聚的信息。
用论文中的例子来直观感受:
这是一个用于评论分类任务的简单元提示结构。在SAMMO框架下,元提示被表示为动态功能图:每个节点根据子节点的结果、输入数据X以及自身的参数θ生成新值。
图中使用输入数据X的节点用浅灰色标注。
Metaprompt π[X]:顶层节点,代表整个元提示函数,接收输入X并输出最终结果。
RenderSection():两个分支的父节点,负责渲染提示的特定部分。
- 左侧的RenderText()节点携带参数θ_text,包含静态文本,例如“在接下来的任务中,你需要分类……”。
- 右侧的RenderSection(X)处理动态内容,即输入数据X。
子节点:
- 左侧RenderText()的子节点包含静态文本:“下面是一些例子:”,用于引出示例数据。
- RenderData()节点有两个实例:一个静态,包含格式化为JSON的示例数据;另一个处理动态输入数据X,同样格式化为JSON。
RenderText()和RenderData(X)节点在右侧协作,渲染任务的具体部分,例如提示用户对输入数据进行分类并以JSON格式展示结果。
该图清晰展示了元提示如何组合多个组件,每个组件各司其职。借助这种结构化方法,我们可以有针对性地修改和优化元提示——比如调整文本说明、更改数据格式或示例——从而提升整体性能。
SAMMO示例
SAMMO的优化过程本质上是在函数图G上搜索,寻找更优的Prompt程序π*。具体来说,SAMMO定义了一系列结构感知变异算子,包括:
- 节点级变换:如重排、替换、删除节点。
- 节点参数变换:如修改指令文本、格式化参数等。
- 图结构层级变换:如增加或删除子节点。
这些变换算子构成了一个庞大的搜索空间Π。SAMMO采用启发式搜索算法——例如遗传算法或beam search——在有限的训练数据上探索该空间,最终找到性能更优的Prompt程序π*。
举一个具体例子。假设我们要构建一个问答系统,用以回答编程语言相关的问题。可以先搭建这样一个Prompt程序:
π = {
"task_description": "Answer questions about programming languages.",
"examples": [
{"question": "What is the difference between Ja va and Python?",
"answer": "Ja va is a statically typed language while Python is dynamically typed. Ja va is generally faster for certain tasks but Python has a simpler and more concise syntax."},
{"question": "How does C++ differ from C?",
"answer": "C++ is an extension of the C programming language, adding object-oriented programming features like classes and inheritance. C++ also has features like function overloading and templates that C does not ha ve."}
],
"format": {
"input": "question: {question}",
"output": "{answer}"
},
"input": "What is the purpose of garbage collection in Ja va?"
}
该Prompt程序包含任务描述、示例问答对以及输入输出格式规范。将其输入LLM,即可获得对应答案。
现在,假设我们要优化这个Prompt,使其在回答编程语言问题时更出色。利用SAMMO的变异算子,可实施以下操作:
- 删除或修改任务描述,使其更明确。
- 增加或替换示例问答对,扩大覆盖范围。
- 调整输入输出格式,使其更简洁易读。
- 重新组织Prompt结构,例如将示例放在末尾。
通过反复迭代这些变换,SAMMO便能探索出一个性能更优的Prompt程序π*,进而用于更流畅的人机交互。
注:论文中变异算子的名称为Prompt Mutation Operators。若对变异提示感兴趣,可查阅DeepMind发布的自主进化提示系统相关文章。
SAMMO应用场景
SAMMO是一个通用的Prompt优化框架,适用于黑盒场景——即优化者只能从LLM的输出中采样。论文证明SAMMO能够概括多种指令优化和压缩技术,并在三个不同应用场景中显著优于现有方法:
1. 指令调优:在8个零样本BigBench分类任务上,SAMMO分别带来10%到100%的性能提升,尤其对较弱的LLM效果更为显著。对于解决某些部署问题,这可能是成本最低、效果最优的方案。
2. 检索增强型生成(RAG)管道调优:在GeoQuery、SMCalFlow和Overnight三个数据集上,SAMMO分别提升了26%到133%的准确率。即使面对强大的GPT-4,也能获得30%的收益。
3. Prompt压缩:在保持基线性能的前提下,SAMMO将Prompt的加权代价(输入输出长度)压缩超过40%,显著优于其他压缩方法。当上下文长度受限时,结构化压缩带来的节省远不止Token。
此外,SAMMO的通用性还体现在其兼容多种已有的Prompt优化与压缩方法,例如自动化Prompt工程(APE)、GrIPS、STDC、Stopwords、GPT-4 Rewrite等。实验结果表明,相比这些方法,SAMMO不仅性能提升更明显,还能实现更大程度的Prompt压缩——尤其在较弱LLM上效果更突出。
这些实验结果释放了一个信号:随着LLM能力不断增强,Prompt的复杂度持续攀升,传统优化方法逐渐力不从心。SAMMO通过将Prompt建模为结构化程序,提供了一种通用且高效的优化路径——既能显著提升Prompt性能,又能大幅压缩开销。对于构建高效的人机交互系统而言,这一方法极具实用价值。掌握SAMMO,可为未来大规模部署LLM打下坚实基础。
需要提醒一点:SAMMO的优化效果会因LLM的不同而呈现差异。这意味着即便使用相同的变异算子,不同LLM的Prompt优化轨迹也只有较弱的相关性。因此,在实际应用中,Prompt优化需要针对具体的LLM进行单独调整。不过总体来看,微软的这项SAMMO确实开创了一种新的Prompt优化范式,为LLM的大规模应用提供了关键支撑。
项目提供了一个示例操作方法和API参考,可在GitHub上搜索“SAMMO”,该项目由Tobias Schnabel编写。
GitHub上的SAMMO示例安装方式对Python版本有特定要求,兼容性不算友好。如果你的开发环境中已有其他版本的Python项目,再安装SAMMO可能会遇到冲突。如果你的机器环境完全干净,没有其他项目,可以直接按照安装教程操作。我也编写了一个Dockerfile,方便一键部署到本地Docker环境。

