Meta 推出的提示词技巧 Prompting Techniques

原文作者 Dalton Flanagan (dalton@meta.com)

原文链接 Prompt_Engineering_with_Llama_2

Meta近日发布了基于Llama 2的提示工程指南,为开发人员、研究人员和爱好者提供了一套全面的提示工程和最佳实践指导。该资源涵盖了多种提示技巧与策略,旨在帮助用户更高效地与大型语言模型进行交互。

这些官方的提示技巧与策略可以作为prompt创作利器。

下文是对原文 Prompting Techniques 部分的翻译,并通过注释(>)的形式进行解释和总结,以便更清晰地传达核心要点。

也可直接跳到文末看总结。

明确指示

详细、明确的指示比开放式提示产生更好的结果:

示例代码:

ini 复制代码
complete_and_print(prompt="用不超过12个词描述量子物理学")
# 返回一个简短的量子物理学解释,提到了粒子和状态的同时存在。

您可以考虑给出明确的指示,例如使用规则和限制来控制 Llama 2 如何响应您的提示。

  • 风格化

    • 像是在儿童教育网络节目上教小学生的一个主题那样向我解释。
    • 我是一个使用大型语言模型进行摘要的软件工程师。请在250字以内总结以下文本:
    • 像一个追踪案件的老派私家侦探那样给出你的答案。
  • 格式化

    • 使用项目符号。
    • 返回一个JSON对象。
    • 使用更少的技术术语,并帮助我在通信工作中应用它。
  • 限制

    • 只使用学术论文。
    • 永远不要使用2020年之前的来源。
    • 如果你不知道答案,就说你不知道。

以下是通过限制响应仅使用最近的来源来给出更具体结果的示例。

示例代码:

bash 复制代码
complete_and_print("向我解释大型语言模型的最新进展。")
# 更有可能引用2017年的来源

complete_and_print("向我解释大型语言模型的最新进展。始终引用你的来源。永远不要引用2020年以前的来源。")
# 提供更具体的进展并且只引用2020年的来源

通过不同语言风格、输出格式、限制条件给出明确的指示,以明确具体任务的边界。例如,如果需要简短解释量子物理,应该直接请求:"以不超过12个词的句子描述量子物理",而不是模糊地问"量子物理是什么?"。

使用 Zero-Shot 和 Few-Shot 学习的示例提示

一个shot是指你期望从大型语言模型中得到什么类型的提示或响应的一个示例或演示。这个术语源于在计算机视觉模型上训练照片,其中 one shot 是模型用来分类图像的一个实例或例子。

Zero-Shot 提示

像Llama 2这样的大型语言模型之所以独特,是因为它们能够在没有事先看到任务示例的情况下遵循指示并产生响应。不使用示例的提示称为"Zero-Shot(零样本)提示"。

让我们尝试使用Llama 2作为情感检测器。你可能会注意到输出格式各不相同

我们可以通过更好的提示来改进这一点。

示例代码:

bash 复制代码
complete_and_print("文本:这是我见过的最好的电影!\n这段文本的情感是:")
# 返回正面情感

complete_and_print("文本:导演太过努力了。\n这段文本的情感是:")
# 返回负面情感

Few-Shot 提示

添加你期望输出的具体示例通常会产生更准确、更一致的输出。这种技术称为"Few-Shot(少样本)提示"。

在这个示例中,生成的响应遵循了我们期望的格式,提供了一个更细致的情感分类器,给出了正面、中性和负面响应的置信度百分比。

参见:Zhao et al. (2021), Liu et al. (2021), Su et al. (2022), Rubin et al. (2022)

示例代码:

scss 复制代码
def sentiment(text):
    response = chat_completion(messages=[
        user("你是一个情感分类器。对每条信息,给出正面/中立/负面的百分比。"),
        user("我喜欢它"),
        assistant("70% 正面 30% 中立 0% 负面"),
        user("它可以更好"),
        assistant("0% 正面 50% 中立 50% 负面"),
        user("它还行"),
        assistant("25% 正面 50% 中立 25% 负面"),
        user(text),
    ])
    return response

def print_sentiment(text):
    print(f'输入:{text}')
    print(sentiment(text))

print_sentiment("我觉得还可以")
# 更有可能返回正面、中立和负面的平衡混合
print_sentiment("我爱它!")
# 更有可能返回100% 正面
print_sentiment("糟糕的服务 0/10")
# 更有可能返回100% 负面

通过几个示例来提高输出的准确性和一致性。文中以user与assistant的对话为示例,生成的内容将遵循想要的格式。

角色提示

当给出一个角色时,Llama 2通常会给出更一致的响应。角色为LLM提供了所需答案类型的上下文。

让我们使用Llama 2为使用PyTorch的利弊问题创建一个更专注、技术性的响应。

示例代码:

bash 复制代码
complete_and_print("解释使用PyTorch的利弊。")
# 更有可能解释PyTorch的利弊,涵盖了文档、PyTorch社区,并提到了陡峭的学习曲线

complete_and_print("你的角色是为处理复杂数据集的高级工程师提供高度技术性建议的机器学习专家。解释使用PyTorch的利弊。")
# 通常会得到更多技术性的好处和缺点,提供更多关于如何处理模型层的技术细节

给模型分配一个角色(如机器学习专家、教师等),以便根据该角色的特点和知识领域提供回答。

思考链 Chain-of-Thought

简单地添加一个鼓励逐步思考的短语"显著提高了大型语言模型执行复杂推理的能力"。这种技术称为"CoT"或"思考链"提示:

示例代码:

bash 复制代码
complete_and_print("谁活得更久,埃尔维斯·普雷斯利还是莫扎特?")
# 通常给出错误答案"莫扎特"

complete_and_print("谁活得更久,埃尔维斯·普雷斯利还是莫扎特?让我们仔细地一步一步地思考。")
# 给出正确答案"埃尔维斯"

在需要复杂推理的任务中,鼓励模型"仔细思考,一步步来",以提高逻辑推理的准确性。

自我一致性

LLM是概率性的,所以即使使用了思考链,单次生成也可能产生错误结果。自我一致性(通过从多次生成中选择最频繁的答案来引入增强的准确性,但代价是更高的计算成本):

示例代码:

python 复制代码
import re
from statistics import mode

def gen_answer():
    response = completion(
        "约翰发现15个数字的平均值是40。"
        "如果每个数字都加上10,那么这些数字的平均值是多少?"
        "请将答案包围在三个反引号中,例如:```123```",
        model = LLAMA2_70B_CHAT
    )
    match = re.search(r'```(\d+)```', response)
    if match is None:
        return None
    return match.group(1)

answers = [gen_answer() for i in range(5)]

print(
    f"答案: {answers}\n",
    f"最终答案: {mode(answers)}",
    )

# Llama-2-70B的示例运行(全部正确):
# [50, 50, 750, 50, 50]  -> 50
# [130, 10, 750, 50, 50] -> 50
# [50, None, 10, 50, 50] -> 50

在每个示例运行中,代码都会生成5个回答(如 [50, 50, 750, 50, 50]),然后从这5个回答中通过 mode(answers) 选择最频繁出现的答案作为最终答案。

通过生成多个回答并选择最一致(频繁出现)的答案来提高准确度,尤其适用于可能有多种解释的情况。

检索增强的生成 Retrieval-Augmented Generation(RAG)

你可能希望在应用中使用事实知识。你可以直接从当今的大型模型中提取常见事实(即仅使用模型权重):

示例代码:

ini 复制代码
complete_and_print("加利福尼亚州的首府是什么?", model = LLAMA2_70B_CHAT)
# 给出正确答案"萨克拉门托"

然而,更具体的事实或私有信息无法可靠地检索。模型将宣称它不知道或者虚构一个错误的答案:

示例代码:

scss 复制代码
complete_and_print("2023年12月12日门洛帕克的温度是多少?")
# "我只是一个AI,我无法访问实时天气数据或历史天气记录。"

complete_and_print("周六我的晚餐预订是什么时间,我应该穿什么?")
# "我无法访问你的个人信息[..]我可以提供一些一般性的指导"

检索增强的生成,或RAG,描述了在提示中包含从外部数据库检索到的信息的做法。这是将事实纳入你的LLM应用的有效方式,比微调更实惠,微调可能成本高昂并对基础模型的能力产生负面影响。

这可以是简单的查找表,也可以是复杂的向量数据库,包含你公司的所有知识:

示例代码:

python 复制代码
MENLO_PARK_TEMPS = {
    "2023-12-11": "52华氏度",
    "2023-12-12": "51华氏度",
    "2023-12-13": "51华氏度",
}


def prompt_with_rag(retrieved_info, question):
    complete_and_print(
        f"根据以下信息:'{retrieved_info}',回答:'{question}'"
    )


def ask_for_temperature(day):
    temp_on_day = MENLO_PARK_TEMPS.get(day) or "未知温度"
    prompt_with_rag(
        f"门洛帕克在{day}的温度是{temp_on_day}'",  # 检索到的事实
        f"门洛帕克在{day}的温度是多少?",  # 用户问题
    )


ask_for_temperature("2023-12-12")
# "当然!门洛帕克在2023-12-12的温度是51华氏度。"

ask_for_temperature("2023-07-18")
# "我无法提供2023-07-18门洛帕克的温度,因为提供的信息表明温度是未知的。"

在需要特定事实或数据时,结合外部检索到的信息来丰富提示内容,增强回答的准确性和实用性。

程序辅助的语言模型 Program-Aided Language Models(PAL)

LLM本质上不擅长执行计算。让我们尝试:

((-5+934-0)(44+(-7)+0*5))

(正确答案是91383。)

示例代码:

python 复制代码
complete_and_print("""
计算以下数学问题的答案:

((-5 + 93 * 4 - 0) * (4^4 + -7 + 0 * 5))
""")
# 给出错误答案,如92448、92648、95463

Gao et al. (2022)引入了"程序辅助的语言模型"(PAL)的概念。虽然LLM不擅长算术,但它们非常适合于代码生成。PAL利用这一事实,指示LLM编写代码以解决计算任务。

示例代码:

python 复制代码
complete_and_print(
    """
    # Python代码计算:((-5 +

 93 * 4 - 0) * (4^4 + -7 + 0 * 5))
    """,
    model="meta/codellama-34b:67942fd0f55b66da802218a19a8f0e1d73095473674061a6ea19f2dc8c053152"
)

示例代码:

ini 复制代码
# 以下代码由Code Llama 34B生成:

num1 = (-5 + 93 * 4 - 0)
num2 = (4**4 + -7 + 0 * 5)
answer = num1 * num2
print(answer)

对于涉及计算或需要精确结果的任务,指示模型生成解决问题的代码,而不是直接尝试回答。

限制多余的token

一个常见的挑战是获得没有多余token(例如"当然!这里有更多关于...的信息")的输出。

看看这个结合了角色、规则和限制、明确指示以及示例的改进:

示例代码:

python 复制代码
complete_and_print(
    "以JSON格式给我门洛帕克的邮政编码,字段名为'zip_code'",
    model = LLAMA2_70B_CHAT,
)
# 可能会返回JSON,也可能会说"当然!这是JSON..."

complete_and_print(
    """
    你是一个只输出JSON的机器人。
    你以字段'zip_code'的JSON格式回复。
    示例问题:帝国大厦的邮政编码是什么?示例答案:{'zip_code': 10118}
    现在这是我的问题:门洛帕克的邮政编码是什么?
    """,
    model = LLAMA2_70B_CHAT,
)
# "{'zip_code': 94025}"

通过综合运用以上技巧,避免在回答中包含不必要的开场白或解释,直接进入核心内容。

总结

一个未经过定制或微调(Fine-tune)的模型,可能不清楚具体任务的边界,也不知道用户的期望。Claude 官方文档里有一个绝妙的比喻:"Claude像一个新来的实习生,不了解公司和老板的偏好,所以需要详细的指导。" 原文见:docs.anthropic.com

为了获得预期的结果,用户需要详细地描述任务,就像熟悉老板口味的咖啡师会根据老板的偏好来冲咖啡一样。Meta 推出的 prompt 技巧将极大地帮助AI能够提供符合用户期望的结果。

  1. 明确指示:提供具体、明确的指示,而不是开放式问题,以获得更精确的结果。
  2. 风格化:通过指定语言风格(如儿童教育节目、老派私家侦探等),可以引导模型生成特定风格的输出。
  3. 格式化:要求模型以特定的格式(如项目符号列表、JSON对象等)输出,有助于提高信息的组织性和实用性。
  4. 限制:通过设置规则和限制(如仅使用特定来源、不使用特定年份之前的信息等),可以确保输出的质量和相关性。
  5. Zero-Shot 和 Few-Shot 学习:Zero-Shot提示不依赖于示例,而Few-Shot提示通过提供几个示例来提高输出的准确性和一致性。
  6. 角色提示:为模型分配一个角色,如机器学习专家,可以帮助它生成更符合角色特点的回答。
  7. 思考链(Chain-of-Thought) :鼓励模型进行逐步推理,以提高复杂问题的解答准确性。
  8. 自我一致性:通过生成多个回答并选择最频繁的答案,可以提高答案的准确性,尽管这会增加计算成本。
  9. 检索增强的生成(Retrieval-Augmented Generation, RAG) :结合外部数据库的信息,可以增强模型在提供事实性回答时的准确性。
  10. 程序辅助的语言模型(Program-Aided Language Models, PAL) :对于计算任务,指示模型生成解决该问题的代码,而不是直接给出答案。
  11. 限制多余的token:通过综合运用上述技巧,可以避免回答中包含不必要的内容,直接提供核心信息。
相关推荐
我是哈哈hh1 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
Tisfy1 小时前
LeetCode 2187.完成旅途的最少时间:二分查找
算法·leetcode·二分查找·题解·二分
Mephisto.java1 小时前
【力扣 | SQL题 | 每日四题】力扣2082, 2084, 2072, 2112, 180
sql·算法·leetcode
robin_suli1 小时前
滑动窗口->dd爱框框
算法
丶Darling.1 小时前
LeetCode Hot100 | Day1 | 二叉树:二叉树的直径
数据结构·c++·学习·算法·leetcode·二叉树
labuladuo5202 小时前
Codeforces Round 977 (Div. 2) C2 Adjust The Presentation (Hard Version)(思维,set)
数据结构·c++·算法
jiyisuifeng19912 小时前
代码随想录训练营第54天|单调栈+双指针
数据结构·算法
꧁༺❀氯ྀൢ躅ྀൢ❀༻꧂2 小时前
实验4 循环结构
c语言·算法·基础题
新晓·故知2 小时前
<基于递归实现线索二叉树的构造及遍历算法探讨>
数据结构·经验分享·笔记·算法·链表
总裁余(余登武)3 小时前
算法竞赛(Python)-万变中的不变“随机算法”
开发语言·python·算法