Few-shot Prompting(少样本提示)概念指南

Few-shot Prompting(少样本提示)概念指南

在这里插入图片描述

前提条件

  • 聊天模型

概述

提高模型性能最有效的方法之一是为模型提供您希望它执行的示例。在模型提示中添加示例输入和预期输出的技术被称为"few-shot prompting"(少样本提示)。这种技术基于《Language Models are Few-Shot Learners》论文。在进行少样本提示时,需要考虑以下几个方面:

  1. 如何生成示例?
  2. 每个提示中包含多少个示例?
  3. 如何在运行时选择示例?
  4. 如何在提示中格式化示例?

以下是对每个方面的详细考虑。

1. 生成示例

少样本提示的第一步也是最重要的步骤是创建一个良好的示例数据集。好的示例应该在运行时相关、清晰、信息丰富,并提供模型之前不知道的信息。

从高层次来看,生成示例的基本方法有:

  • 手动生成:人工生成他们认为有用的示例。
  • 更好的模型:使用更好的(通常更昂贵/更慢的)模型的响应作为较差的(通常更便宜/更快的)模型的示例。
  • 用户反馈:用户(或标注者)对应用程序交互留下反馈,基于该反馈生成示例(例如,所有获得正面反馈的交互都可以转化为示例)。
  • LLM反馈:与用户反馈相同,但通过让模型评估自己来自动化这个过程。

哪种方法最好取决于您的任务。对于需要真正理解少数核心原则的任务,手工制作几个真正好的示例可能很有价值。对于正确行为空间更广泛、更细致的任务,以更自动化的方式生成许多示例可能很有用,这样对于任何运行时输入都有更高的可能性存在一些高度相关的示例。

单轮 vs 多轮示例

生成示例时要考虑的另一个维度是示例实际展示的内容。

最简单的示例类型只有用户输入和预期的模型输出。这些是单轮示例。

一种更复杂的示例类型是整个对话的示例,通常是模型最初响应错误,然后用户告诉模型如何纠正其答案。这被称为多轮示例。多轮示例对于更细致的任务很有用,在这些任务中,展示常见错误并详细说明为什么它们是错误的以及应该做什么是有用的。

2. 示例数量

一旦我们有了示例数据集,我们需要考虑每个提示中应该包含多少个示例。关键的权衡是,更多的示例通常会提高性能,但更大的提示会增加成本和延迟。超过某个阈值,拥有太多示例可能会开始混淆模型。找到正确的示例数量高度依赖于模型、任务、示例质量以及您的成本和延迟约束。据传闻,模型越好,执行良好所需的示例就越少,添加更多示例的收益递减就越快。但是,可靠回答这个问题的最佳/唯一方法是使用不同数量的示例运行一些实验。

3. 选择示例

假设我们不会将整个示例数据集添加到每个提示中,我们需要有一种基于给定输入从数据集中选择示例的方法。我们可以这样做:

  • 随机选择
  • 基于输入的(语义或关键词)相似性
  • 基于其他约束,如令牌大小

LangChain有许多ExampleSelectors,使得使用这些技术中的任何一种都变得容易。

通常,按语义相似性选择会导致最佳的模型性能。但这有多重要再次取决于模型和任务,值得进行实验。

4. 格式化示例

现在大多数最先进的模型都是聊天模型,所以我们将专注于为这些模型格式化示例。我们的基本选项是将示例插入:

  • 在系统提示中作为字符串
  • 作为它们自己的消息

如果我们将示例作为字符串插入系统提示中,我们需要确保模型清楚地知道每个示例从哪里开始,哪些部分是输入,哪些是输出。不同的模型对不同的语法响应更好,如ChatML、XML、TypeScript等。

如果我们将示例作为消息插入,其中每个示例表示为一系列Human、AI消息,我们可能还想为我们的消息分配名称,如"example_user""example_assistant",以明确这些消息对应于与最新输入消息不同的参与者。

格式化工具调用示例

当我们的示例输出有工具调用时,将示例格式化为消息可能会很棘手。这是因为不同的模型对生成任何工具调用时允许的消息序列类型有不同的约束。

  • 一些模型要求任何带有工具调用的AIMessage必须立即跟随每个工具调用的ToolMessages,
  • 一些模型还要求任何ToolMessages必须立即跟随AIMessage,然后才是下一个HumanMessage,
  • 一些模型要求如果聊天历史中有任何工具调用/ToolMessages,则必须将工具传递到模型中。

这些要求是特定于模型的,应该为您使用的模型进行检查。如果您的模型在工具调用后需要ToolMessages和/或在ToolMessages后需要AIMessages,而您的示例只包括预期的工具调用而不包括实际的工具输出,您可以尝试在每个示例的末尾添加具有通用内容的虚拟ToolMessages/AIMessages以满足API约束。在这些情况下,特别值得尝试将示例作为字符串与消息插入,因为虚拟消息可能会对某些模型产生不利影响。

您可以在这里查看Anthropic和OpenAI如何在两个不同的工具调用基准测试中响应不同的少样本提示技术的案例研究。

总结

Few-shot prompting是一种强大的技术,可以显著提高语言模型的性能。关键要点包括:

  1. 示例质量至关重要:好的示例应该相关、清晰且信息丰富
  2. 数量需要平衡:更多示例通常更好,但会增加成本和延迟
  3. 选择策略很重要:语义相似性通常是最佳选择方法
  4. 格式化需要考虑模型特性:不同模型对不同格式的响应不同

通过仔细考虑这些因素并进行实验,您可以有效地使用few-shot prompting来改善您的LangChain应用程序的性能。


本文档基于LangChain官方文档翻译和整理

### Few-Shot 学习与 CLIP 模型的应用及实现 Few-shot 学习是一种机器学习范式,旨在利用少量样本完成特定任务的学习目标。CLIP(Contrastive Language–Image Pre-training)作为一种强大的多模态预训练模型,在 few-shot 场景下表现出显著的优势[^1]。 #### LAMM 方法概述 为了进一步提升 CLIP 的 zero-shotfew-shot 性能,研究者提出了 LAMM(Learnable Adaptive Multimodal Matching)。该方法的核心在于通过端到端的方式优化标签嵌入,从而缩小图像特征与其对应类别表示之间的差距。具体而言,LAMM 将 prompt 中的固定文本模板替换为可学习的标记 \(< M_i >\) (\(i=1, 2, ..., k\),这些标记代表不同类别的语义信息。在训练阶段,仅需更新每个下游数据集中对应的类别向量集合 \(\{< M_i >\}_{i=1}^{k}\),而不改变 CLIP 预训练权重。 这种设计不仅保留了 CLIP 原有的跨模态理解能力,还增强了其针对特定领域或任务的适应性。例如,在 CoOp(Context Optimization Prompting)框架基础上引入 LAMM 后,可以通过用可训练向量替代原始类别描述来改进提示模板结构。 以下是基于 PyTorch 实现的一个简化版代码片段展示如何结合 LAMM 进行 fine-tuning: ```python import torch from clip import load as load_clip device = "cuda" if torch.cuda.is_available() else "cpu" model, preprocess = load_clip("ViT-B/32", device=device) class LearnablePrompt(torch.nn.Module): def __init__(self, num_classes, embedding_dim=512): super().__init__() self.learned_prompts = torch.nn.ParameterList([ torch.nn.Parameter(torch.randn(1, embedding_dim)) for _ in range(num_classes)]) def forward(self, class_indices=None): if class_indices is None: return torch.cat([p for p in self.learned_prompts]) else: return torch.stack([self.learned_prompts[i][0] for i in class_indices]) def compute_similarity(image_features, text_features): image_features /= image_features.norm(dim=-1, keepdim=True) text_features /= text_features.norm(dim=-1, keepdim=True) logit_scale = model.logit_scale.exp() logits_per_image = logit_scale * image_features @ text_features.t() return logits_per_image # Example usage of the learnable prompts module. num_classes = 10 learnable_prompt_module = LearnablePrompt(num_classes).to(device) optimizer = torch.optim.AdamW(learnable_prompt_module.parameters(), lr=1e-3) for epoch in range(epochs): optimizer.zero_grad() images = ... # Load batch of images labels = ... # Corresponding labels processed_images = [preprocess(img) for img in images] tensor_stack = torch.stack(processed_images).to(device) with torch.no_grad(): image_features = model.encode_image(tensor_stack) learned_text_embeddings = learnable_prompt_module(labels) similarity_scores = compute_similarity(image_features, learned_text_embeddings) loss_fn = torch.nn.CrossEntropyLoss() loss = loss_fn(similarity_scores, labels.to(device)) loss.backward() optimizer.step() ``` 上述代码展示了如何定义并训练一个简单的可学习提示模块 `LearnablePrompt` 来适配不同的分类任务需求。值得注意的是,实际部署时可能还需要考虑更多细节调整以及更复杂的网络架构设计以满足更高精度的要求。 #### 结论 综上所述,借助像 LAMM 这样的技术手段能够极大地提高 CLIP 在 small-data regimes 下的表现效果。通过对类别嵌入表征进行微调操作而非重新训练整个神经网络参数组,则既节省资源又保持住了原有泛化特性的同时实现了定制化的功能扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值