少样本提示
概述
提高模型性能最有效的方法之一是向模型提供你希望它执行的操作示例。将示例输入和预期输出添加到模型提示的技术称为“少样本提示”。该技术基于 语言模型是少样本学习者 论文。 在进行少样本提示时,有几件事需要考虑:
- 示例是如何生成的?
- 每个提示中有多少个示例?
- 如何在运行时选择示例?
- 示例在提示中如何格式化?
以下是针对每个问题的考虑因素。
1. 生成示例
少样本提示的第一步也是最重要的一步是提出一个好的示例数据集。好的示例应该在运行时相关、清晰、信息丰富,并提供模型尚未知道的信息。
从高层次来看,生成示例的基本方法有:
- 手动:由一个人/多人生成他们认为有用的示例。
- 更好的模型:使用更好的(可能更昂贵/更慢的)模型的响应作为更差(可能更便宜/更快的)模型的示例。
- 用户反馈:用户(或标记员)对与应用程序的交互留下反馈,并根据该反馈生成示例(例如,所有具有积极反馈的交互都可以转换为示例)。
- LLM 反馈:与用户反馈相同,但该过程通过让模型自我评估来实现自动化。
哪种方法最好取决于你的任务。对于需要很好地理解少量核心原则的任务,手工制作一些非常好的示例可能会很有价值。对于正确行为的空间更广泛、更细致的任务,以更自动化的方式生成大量示例可能很有用,这样更有可能为任何运行时输入提供一些高度相关的示例。
单轮示例与多轮示例
生成示例时要考虑的另一个维度是示例实际显示的内容。
最简单的示例类型只有用户输入和预期的模型输出。这些是单轮示例。
一种更复杂的示例类型是整个对话的示例,通常是模型最初响应不正确,然后用户告诉模型如何纠正其答案。这称为多轮示例。多轮示例对于更细致的任务可能很有用,在这些任务中,展示常见错误并明确说明它们为什么是错误的以及应该做什么很有用。
2. 示例数量
一旦我们有了示例数据集,我们需要考虑每个提示中应该有多少个示例。关键的权衡是,更多的示例通常会提高性能,但更大的提示会增加成本和延迟。并且超出某个阈值,添加太多示例可能会开始混淆模型。找到正确数量的示例高度依赖于模型、任务、示例质量以及你的成本和延迟约束。根据传闻,模型越好,它需要执行的示例就越少,并且你添加更多示例时达到收益递减的速度就越快。但是,可靠地回答此问题的最佳/唯一方法是对不同数量的示例进行一些实验。
3. 选择示例
假设我们没有将整个示例数据集添加到每个提示中,我们需要一种根据给定输入从数据集中选择示例的方法。我们可以这样做:
- 随机选择
- 按输入(语义或基于关键字的)相似性
- 基于其他一些约束,例如令牌大小
LangChain 有许多 ExampleSelectors
,可以轻松使用这些技术中的任何一种。
通常,按语义相似性选择会导致最佳模型性能。但这有多重要再次取决于模型和任务,并且值得尝试。
4. 格式化示例
现在大多数最先进的模型都是聊天模型,因此我们将重点关注如何格式化这些模型的示例。我们的基本选择是将示例插入:
- 在系统提示中作为字符串
- 作为他们自己的消息
如果我们以字符串形式将示例插入系统提示中,则需要确保模型清楚地知道每个示例从何处开始以及哪些部分是输入与输出。不同的模型对不同的语法有更好的响应,例如 ChatML、XML、TypeScript 等。
如果我们将示例作为消息插入,其中每个示例都表示为 Human 和 AI 消息的序列,我们可能还希望为我们的消息分配 名称,如 "example_user"
和 "example_assistant"
,以明确这些消息对应于与最新输入消息不同的参与者。
格式化工具调用示例
将示例格式化为消息时,一个棘手的问题是当我们的示例输出具有工具调用时。这是因为不同的模型对生成任何工具调用时允许的消息序列类型有不同的约束。
- 一些模型要求任何带有工具调用的 AIMessage 之后必须立即跟随每个工具调用的 ToolMessage,
- 一些模型还要求任何 ToolMessage 之后必须立即跟随 AIMessage,然后才能出现下一个 HumanMessage,
- 如果聊天历史记录中有任何工具调用/ToolMessage,一些模型要求将工具传递给模型。
这些要求是特定于模型的,应针对你正在使用的模型进行检查。如果你的模型要求工具调用后有 ToolMessage 和/或 ToolMessage 后有 AIMessage,并且你的示例仅包含预期的工具调用而不是实际的工具输出,你可以尝试在每个示例的末尾添加带有通用内容的虚拟 ToolMessage/AIMessage,以满足 API 约束。在这些情况下,尤其值得尝试将你的示例作为字符串插入而不是作为消息插入,因为使用虚拟消息会对某些模型产生不利影响。
你可以在 此处 看到 Anthropic 和 OpenAI 如何在两个不同的工具调用基准上响应不同的少样本提示技术的案例研究。