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