LLM 提示指南
像 Falcon、LLaMA 等大型语言模型是预训练的 Transformer 模型,最初训练目的是根据一些输入文本预测下一个词元。它们通常具有数十亿个参数,并且已经在数万亿个词元上训练了很长时间。因此,这些模型变得非常强大且用途广泛,您可以通过使用自然语言提示来指导模型,开箱即用地使用它们来解决多种 NLP 任务。
设计这样的提示以确保最佳输出通常被称为“提示工程”。提示工程是一个需要大量实验的迭代过程。自然语言比编程语言灵活得多,表达能力也更强,但是,它们也可能引入一些歧义。同时,自然语言中的提示对变化非常敏感。即使是提示中微小的修改也可能导致截然不同的输出。
虽然没有确切的配方可以创建适用于所有情况的提示,但研究人员已经制定了一些最佳实践,可以帮助更一致地实现最佳结果。
本指南涵盖提示工程的最佳实践,以帮助您创建更好的 LLM 提示并解决各种 NLP 任务。您将学习
提示工程只是 LLM 输出优化过程的一部分。另一个重要组成部分是选择最佳的文本生成策略。您可以自定义 LLM 在生成文本时选择每个后续词元的方式,而无需修改任何可训练参数。通过调整文本生成参数,您可以减少生成的文本中的重复,并使其更连贯,更像人类的语言。文本生成策略和参数在本指南中不包括在内,但您可以在以下指南中了解更多有关这些主题的信息
提示基础
模型类型
大多数现代 LLM 是解码器专用的 Transformer。一些例子包括:LLaMA、Llama2、Falcon、GPT2。但是,您也可能会遇到编码器-解码器 Transformer LLM,例如,Flan-T5 和 BART。
编码器-解码器风格的模型通常用于生成任务,其中输出**严重**依赖于输入,例如,在翻译和摘要中。解码器专用的模型用于所有其他类型的生成任务。
使用管道使用 LLM 生成文本时,重要的是要知道您使用的是哪种类型的 LLM,因为它们使用不同的管道。
使用 text-generation
管道使用解码器专用模型运行推理
>>> from transformers import pipeline
>>> import torch
>>> torch.manual_seed(0)
>>> generator = pipeline('text-generation', model = 'openai-community/gpt2')
>>> prompt = "Hello, I'm a language model"
>>> generator(prompt, max_length = 30)
[{'generated_text': "Hello, I'm a language model programmer so you can use some of my stuff. But you also need some sort of a C program to run."}]
要使用编码器-解码器运行推理,请使用 text2text-generation
管道
>>> text2text_generator = pipeline("text2text-generation", model = 'google/flan-t5-base')
>>> prompt = "Translate from English to French: I'm very happy to see you"
>>> text2text_generator(prompt)
[{'generated_text': 'Je suis très heureuse de vous rencontrer.'}]
基础模型与指令/聊天模型
🤗 Hub 上提供的大多数最近的 LLM 检查点都以两种版本提供:基础版本和指令版本(或聊天版本)。例如,tiiuae/falcon-7b
和 tiiuae/falcon-7b-instruct
。
基础模型在给定初始提示时非常擅长完成文本,但是,它们不适合需要遵循指令的 NLP 任务,也不适合对话使用。这就是指令(聊天)版本发挥作用的地方。这些检查点是预训练的基础版本的进一步微调结果,这些基础版本在指令和对话数据上进行了微调。这种额外的微调使它们成为许多 NLP 任务的更好选择。
让我们说明一些您可以与 tiiuae/falcon-7b-instruct
一起使用的简单提示,以解决一些常见的 NLP 任务。
NLP 任务
首先,让我们设置环境
pip install -q transformers accelerate
接下来,让我们使用适当的管道("text-generation"
)加载模型
>>> from transformers import pipeline, AutoTokenizer
>>> import torch
>>> torch.manual_seed(0)
>>> model = "tiiuae/falcon-7b-instruct"
>>> tokenizer = AutoTokenizer.from_pretrained(model)
>>> pipe = pipeline(
... "text-generation",
... model=model,
... tokenizer=tokenizer,
... torch_dtype=torch.bfloat16,
... device_map="auto",
... )
请注意,Falcon 模型使用 bfloat16
数据类型进行了训练,因此我们建议您使用相同的类型。这需要最新版本的 CUDA,并且在现代显卡上效果最佳。
现在我们已经通过管道加载了模型,让我们探索如何使用提示来解决 NLP 任务。
文本分类
文本分类最常见的形式之一是情感分析,它为一段文本分配一个标签,例如“正面”、“负面”或“中性”。让我们编写一个提示来指示模型对给定文本(电影评论)进行分类。我们将从给出指令开始,然后指定要分类的文本。请注意,我们并没有止步于此,而是还添加了响应的开头 - "Sentiment: "
>>> torch.manual_seed(0)
>>> prompt = """Classify the text into neutral, negative or positive.
... Text: This movie is definitely one of my favorite movies of its kind. The interaction between respectable and morally strong characters is an ode to chivalry and the honor code amongst thieves and policemen.
... Sentiment:
... """
>>> sequences = pipe(
... prompt,
... max_new_tokens=10,
... )
>>> for seq in sequences:
... print(f"Result: {seq['generated_text']}")
Result: Classify the text into neutral, negative or positive.
Text: This movie is definitely one of my favorite movies of its kind. The interaction between respectable and morally strong characters is an ode to chivalry and the honor code amongst thieves and policemen.
Sentiment:
Positive
结果,输出包含我们已经在指令中提供的列表中的分类标签,并且它是正确的!
您可能会注意到,除了提示之外,我们还传递了一个 max_new_tokens
参数。它控制模型将生成多少个词元,它是您可以从 文本生成策略 指南中了解的许多文本生成参数之一。
命名实体识别
命名实体识别 (NER) 是在一段文本中查找命名实体的任务,例如人、地点或组织。让我们修改提示中的指令以使 LLM 执行此任务。在这里,我们还设置 return_full_text = False
,这样输出就不会包含提示
>>> torch.manual_seed(1)
>>> prompt = """Return a list of named entities in the text.
... Text: The Golden State Warriors are an American professional basketball team based in San Francisco.
... Named entities:
... """
>>> sequences = pipe(
... prompt,
... max_new_tokens=15,
... return_full_text = False,
... )
>>> for seq in sequences:
... print(f"{seq['generated_text']}")
- Golden State Warriors
- San Francisco
如您所见,模型从给定文本中正确识别了两个命名实体。
翻译
大型语言模型 (LLM) 可以执行的另一项任务是翻译。您可以选择为此任务使用编码器-解码器模型,但是,为了简化示例,我们将继续使用 Falcon-7b-instruct,它在这方面表现还不错。再次,以下是如何编写一个基本提示,以指示模型将一段文本从英语翻译成意大利语
>>> torch.manual_seed(2)
>>> prompt = """Translate the English text to Italian.
... Text: Sometimes, I've believed as many as six impossible things before breakfast.
... Translation:
... """
>>> sequences = pipe(
... prompt,
... max_new_tokens=20,
... do_sample=True,
... top_k=10,
... return_full_text = False,
... )
>>> for seq in sequences:
... print(f"{seq['generated_text']}")
A volte, ho creduto a sei impossibili cose prima di colazione.
在这里,我们添加了 do_sample=True
和 top_k=10
以允许模型在生成输出时更灵活。
文本摘要
与翻译类似,文本摘要是另一个生成式任务,其中输出严重依赖输入,编码器-解码器模型可能是更好的选择。但是,解码器类型的模型也可以用于此任务。之前,我们将指令放在提示的最开头。但是,提示的最后也是指令的合适位置。通常,最好将指令放在其中一个极端位置。
>>> torch.manual_seed(3)
>>> prompt = """Permaculture is a design process mimicking the diversity, functionality and resilience of natural ecosystems. The principles and practices are drawn from traditional ecological knowledge of indigenous cultures combined with modern scientific understanding and technological innovations. Permaculture design provides a framework helping individuals and communities develop innovative, creative and effective strategies for meeting basic needs while preparing for and mitigating the projected impacts of climate change.
... Write a summary of the above text.
... Summary:
... """
>>> sequences = pipe(
... prompt,
... max_new_tokens=30,
... do_sample=True,
... top_k=10,
... return_full_text = False,
... )
>>> for seq in sequences:
... print(f"{seq['generated_text']}")
Permaculture is an ecological design mimicking natural ecosystems to meet basic needs and prepare for climate change. It is based on traditional knowledge and scientific understanding.
问答
对于问答任务,我们可以将提示结构化为以下逻辑组件:指令、上下文、问题和引导词或短语("Answer:"
)以鼓励模型开始生成答案
>>> torch.manual_seed(4)
>>> prompt = """Answer the question using the context below.
... Context: Gazpacho is a cold soup and drink made of raw, blended vegetables. Most gazpacho includes stale bread, tomato, cucumbers, onion, bell peppers, garlic, olive oil, wine vinegar, water, and salt. Northern recipes often include cumin and/or pimentón (smoked sweet paprika). Traditionally, gazpacho was made by pounding the vegetables in a mortar with a pestle; this more laborious method is still sometimes used as it helps keep the gazpacho cool and avoids the foam and silky consistency of smoothie versions made in blenders or food processors.
... Question: What modern tool is used to make gazpacho?
... Answer:
... """
>>> sequences = pipe(
... prompt,
... max_new_tokens=10,
... do_sample=True,
... top_k=10,
... return_full_text = False,
... )
>>> for seq in sequences:
... print(f"Result: {seq['generated_text']}")
Result: Modern tools often used to make gazpacho include
推理
推理是 LLM 最难的任务之一,要获得良好的结果,通常需要应用高级提示技术,例如思维链。
让我们尝试一下,是否可以使用基本提示让模型对一个简单的算术任务进行推理
>>> torch.manual_seed(5)
>>> prompt = """There are 5 groups of students in the class. Each group has 4 students. How many students are there in the class?"""
>>> sequences = pipe(
... prompt,
... max_new_tokens=30,
... do_sample=True,
... top_k=10,
... return_full_text = False,
... )
>>> for seq in sequences:
... print(f"Result: {seq['generated_text']}")
Result:
There are a total of 5 groups, so there are 5 x 4=20 students in the class.
正确!让我们稍微增加一下复杂度,看看我们是否仍然可以使用基本提示
>>> torch.manual_seed(6)
>>> prompt = """I baked 15 muffins. I ate 2 muffins and gave 5 muffins to a neighbor. My partner then bought 6 more muffins and ate 2. How many muffins do we now have?"""
>>> sequences = pipe(
... prompt,
... max_new_tokens=10,
... do_sample=True,
... top_k=10,
... return_full_text = False,
... )
>>> for seq in sequences:
... print(f"Result: {seq['generated_text']}")
Result:
The total number of muffins now is 21
这是一个错误的答案,应该为 12。在这种情况下,这可能是由于提示过于简单,也可能是由于模型的选择,毕竟我们选择了 Falcon 的最小版本。推理对于各种大小的模型都很困难,但更大的模型可能会表现更好。
LLM 提示的最佳实践
在本指南的这一部分中,我们整理了一些最佳实践,这些实践往往可以改善提示结果
- 在选择要使用的模型时,最新且最强大的模型可能会表现更好。
- 从一个简单而简短的提示开始,然后从那里进行迭代。
- 将指令放在提示的开头,或放在最后。在处理大型上下文时,模型会应用各种优化措施,以防止注意力复杂度按二次方扩展。这可能会使模型更关注提示的开头或结尾,而不是中间。
- 清楚地将指令与其适用的文本区分开来 - 下一节将详细介绍这一点。
- 对任务和预期结果进行具体和描述性的说明 - 其格式、长度、风格、语言等。
- 避免含糊不清的描述和说明。
- 更倾向于说明“做什么”的指令,而不是说明“不做什么”的指令。
- 通过写下第一个词(甚至为模型开始第一句话)来“引导”输出到正确的方向。
- 使用少样本提示和思维链等高级技术
- 使用不同的模型测试你的提示,以评估它们的稳健性。
- 版本控制和跟踪你的提示的性能。
高级提示技术
少样本提示
上面各节中的基本提示是“零样本”提示的示例,这意味着,模型已经获得了指令和上下文,但没有提供带有解决方案的示例。在指令数据集上经过微调的 LLM 通常在这样的“零样本”任务中表现良好。但是,您可能会发现您的任务有更多复杂性或细微差别,并且,也许,您对输出有一些要求,模型无法仅仅从指令中理解。在这种情况下,您可以尝试一种称为少样本提示的技术。
在少样本提示中,我们提供提示中的示例,为模型提供更多上下文以提高性能。示例会使模型适应生成遵循示例中模式的输出。
以下是一个示例
>>> torch.manual_seed(0)
>>> prompt = """Text: The first human went into space and orbited the Earth on April 12, 1961.
... Date: 04/12/1961
... Text: The first-ever televised presidential debate in the United States took place on September 28, 1960, between presidential candidates John F. Kennedy and Richard Nixon.
... Date:"""
>>> sequences = pipe(
... prompt,
... max_new_tokens=8,
... do_sample=True,
... top_k=10,
... )
>>> for seq in sequences:
... print(f"Result: {seq['generated_text']}")
Result: Text: The first human went into space and orbited the Earth on April 12, 1961.
Date: 04/12/1961
Text: The first-ever televised presidential debate in the United States took place on September 28, 1960, between presidential candidates John F. Kennedy and Richard Nixon.
Date: 09/28/1960
在上面的代码片段中,我们使用了一个示例来向模型展示所需的输出,因此这可以称为“单样本”提示。但是,根据任务的复杂性,您可能需要使用多个示例。
少样本提示技术的局限性
- 虽然 LLM 可以从示例中学习模式,但这种技术在复杂的推理任务中效果不佳
- 少样本提示需要创建冗长的提示。带有大量 token 的提示会增加计算量和延迟。提示的长度也有限制。
- 有时,在给出一些示例后,模型可能会学习到您没有打算让它们学习的模式,例如,第三个电影评论总是负面的。
思维链
思维链 (CoT) 提示是一种技术,它可以鼓励模型产生中间推理步骤,从而改善复杂推理任务的结果。
引导模型产生推理步骤有两种方法
- 通过少样本提示,提供带有详细答案的示例,向模型展示如何解决问题。
- 通过指示模型进行推理,添加诸如“让我们一步一步思考”或“深呼吸,一步一步地解决问题。”之类的短语。
如果我们将 CoT 技术应用于推理部分中的松饼示例,并使用更大的模型,例如 (tiiuae/falcon-180B-chat
),您可以在HuggingChat中尝试,我们将在推理结果方面获得显著的改进
Let's go through this step-by-step: 1. You start with 15 muffins. 2. You eat 2 muffins, leaving you with 13 muffins. 3. You give 5 muffins to your neighbor, leaving you with 8 muffins. 4. Your partner buys 6 more muffins, bringing the total number of muffins to 14. 5. Your partner eats 2 muffins, leaving you with 12 muffins. Therefore, you now have 12 muffins.
提示与微调
通过优化你的提示,你可以获得很棒的结果,但是你可能仍然会思考微调模型是否更适合你的情况。以下是一些微调较小模型可能成为首选方案的场景。
- 你的领域与 LLMs 预训练的内容大不相同,并且大量的提示优化并没有产生足够的结果。
- 你需要你的模型在低资源语言中表现良好。
- 你需要模型在受严格监管的敏感数据上进行训练。
- 由于成本、隐私、基础设施或其他限制,你必须使用小型模型。
在以上所有示例中,你需要确保你已经拥有或可以轻松获得足够大的特定领域数据集,并且成本合理,以便微调模型。你还需要有足够的时间和资源来微调模型。
如果以上示例不适用于你,优化提示可能会证明更有效。
< > 更新 在 GitHub 上