在大语言模型(LLM)蓬勃发展的今天,如何有效地与模型交互成为了每个开发者必须面对的核心问题。Prompt Engineering(提示工程)作为一门新兴学科,专注于研究如何设计最优的提示词来引导模型产生期望的输出。可以说,掌握了提示工程,就等于拥有了在 AI 时代高效解决问题的能力。
Few-Shot Learning(少样本学习)是 Prompt Engineering 中最核心、最实用的技术之一。它允许我们在不进行模型微调的情况下,通过在提示中提供少量示例来显著提升模型的推理能力。这种方法既避免了耗时且需要大量 GPU 资源的微调过程,又能快速适配各种特定任务场景。
问题描述
许多开发者在使用 LLM 时会遇到这样的困境:模型虽然能力强大,但在处理特定领域任务时往往无法准确理解需求。即使提供了详细的指令,模型仍然会给出模棱两可或不准确的回答。
例如,假设你需要让模型对用户评论进行情感分类。如果你只是简单地说「判断下面文本的情感是正面还是负面」,模型可能会给出不一致的答案,有时甚至会误解某些表达方式。
为什么会这样?因为模型在预训练阶段学习的是通用语言模式,缺乏对特定任务格式和逻辑的深入理解。传统的解决方案是进行模型微调,但这需要大量的标注数据和计算资源,对于很多中小型团队来说并不现实。
Few-Shot Learning 提供了一个更优雅的解决方案:在提示中直接包含几个完成任务的示例,让模型通过这些示例来理解任务的本质和期望的输出格式。这种方法既避免了微调的高成本,又能快速适配各种任务场景。
详细步骤
环境准备
首先,我们需要安装必要的依赖:
pip install langchain langchain-openai chromadb
基础实现:使用 LangChain 构建 Few-Shot 提示
LangChain 提供了 FewShotPromptTemplate 类,专门用于构建少样本学习提示。让我通过完整的代码示例来演示。
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
from langchain.prompts.example_selector import LengthBasedExampleSelector
# 定义训练示例 - 情感分类任务
examples = [
{
"input": "今天天气真好,阳光明媚!",
"sentiment": "正面"
},
{
"input": "这个产品太差了,完全浪费钱",
"sentiment": "负面"
},
{
"input": "今天吃了饭,没什么特别的感觉",
"sentiment": "中性"
}
]
# 创建示例模板
example_prompt = PromptTemplate(
input_variables=["input", "sentiment"],
template="文本: {input}\n情感: {sentiment}"
)
# 使用 LengthBasedExampleSelector 自动选择示例
example_selector = LengthBasedExampleSelector(
examples=examples,
example_prompt=example_prompt,
max_length=100
)
# 创建少样本提示模板
few_shot_prompt_template = FewShotPromptTemplate(
example_selector=example_selector,
example_prompt=example_prompt,
prefix="判断下面文本的情感倾向,只需要回答正面、负面或中性:",
suffix="文本: {input}\n情感:",
input_variables=["input"],
example_separator="\n\n"
)
# 打印生成的提示
print("=== 生成的提示 ===")
print(few_shot_prompt_template.format(input="太棒了!"))
调用模型进行推理
from langchain_openai import ChatOpenAI
# 初始化模型
llm = ChatOpenAI(
model="gpt-3.5-turbo",
api_key="your-api-key" # 替换为你的 API Key
)
# 创建完整的处理链
chain = few_shot_prompt_template | llm
# 测试不同的输入
test_inputs = [
"太棒了,完全超出预期!",
"有点失望,不太满意",
"明天有会议",
"这部电影是近年来最好的",
"服务态度太差了,我要投诉"
]
print("\n=== 运行结果 ===")
for test_input in test_inputs:
result = chain.invoke({"input": test_input})
print(f"输入: {test_input}")
print(f"情感: {result.content}")
print("-" * 40)
运行结果
运行上述代码后,我们得到了以下结果:
=== 运行结果 === 输入: 太棒了,完全超出预期! 情感: 正面 ---------------------------------------- 输入: 有点失望,不太满意 情感: 负面 ---------------------------------------- 输入: 明天有会议 情感: 中性 ---------------------------------------- 输入: 这部电影是近年来最好的 情感: 正面 ---------------------------------------- 输入: 服务态度太差了,我要投诉 情感: 负面 ----------------------------------------
可以看到,Few-Shot Learning 展现出了强大的能力。模型不仅能正确识别明显带有情感倾向的文本(如「太棒了」、「太差了」),还能处理一些较为隐晦的表达(如「不太满意」、「近年来最好的」)。
进阶技巧
1. 动态示例选择
固定示例并不总是最优选择。LangChain 提供了基于语义相似度的示例选择器,可以根据输入自动选择最相关的示例:
from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
# 扩展示例库
examples_extended = [
{"input": "今天天气真好", "sentiment": "正面"},
{"input": "太喜欢这个了", "sentiment": "正面"},
{"input": "非常满意", "sentiment": "正面"},
{"input": "产品太差了", "sentiment": "负面"},
{"input": "非常失望", "sentiment": "负面"},
{"input": "不推荐购买", "sentiment": "负面"},
{"input": "今天吃了饭", "sentiment": "中性"},
{"input": "明天有会议", "sentiment": "中性"},
{"input": "这是什么意思", "sentiment": "中性"},
# 添加复杂案例
{"input": "这个产品好是好,就是太贵了", "sentiment": "中性"}, # 转折句
{"input": "简直无语了", "sentiment": "负面"}, # 网络用语
]
# 基于语义相似度选择示例
example_selector = SemanticSimilarityExampleSelector.from_examples(
examples_extended,
OpenAIEmbeddings(),
Chroma,
k=3 # 选择最相似的3个示例
)
2. 示例格式规范化
为了让模型输出更稳定,我们可以在示例中明确指定输出格式:
# 更规范的示例格式
examples_formatted = [
{
"input": "今天天气真好",
"sentiment": "正面",
"reason": "包含积极的表达词汇"
},
{
"input": "这个产品太差了",
"sentiment": "负面",
"reason": "包含消极的评价词汇"
}
]
example_prompt_formatted = PromptTemplate(
input_variables=["input", "sentiment", "reason"],
template="文本: {input}\n情感: {sentiment}\n原因: {reason}"
)
3. 思维链提示
对于需要推理的任务,可以在示例中加入推理过程:
# 思维链示例
cot_examples = [
{
"input": "我有3个苹果,妈妈又给了2个,我吃了1个,还剩几个?",
"reasoning": "3 + 2 = 5,5 - 1 = 4",
"answer": "4个"
},
{
"input": "小明有10本书,借给小红3本,又买了5本,现在有多少本?",
"reasoning": "10 - 3 = 7,7 + 5 = 12",
"answer": "12本"
}
]
cot_prompt = PromptTemplate(
input_variables=["input", "reasoning", "answer"],
template="问题: {input}\n思考过程: {reasoning}\n答案: {answer}"
)
总结
Few-Shot Learning 是 Prompt Engineering 中最强大的技术之一,它通过在提示中提供少量示例,让模型能够快速理解任务需求并给出准确的回答。本文通过 LangChain 的完整代码示例,展示了如何构建企业级的少样本学习提示系统。
关键要点总结:
- Few-Shot Learning 的核心优势:无需微调,快速适配新任务,效果显著
- 示例选择很重要:使用语义相似度选择器可以显著提升效果
- 格式规范化:明确的输入输出格式可以让模型输出更稳定
- 思维链提示:对于复杂推理任务,在示例中加入推理过程可以提升准确率
通过合理运用 Few-Shot Learning 技术,我们可以充分发挥大语言模型的潜力,在各种实际应用场景中取得出色的效果。