😄 为了更好地与大模型(e.g. chatgpt)更好的交流,一起来学习如何写prompt吧!😄
文章目录
- 1、简介
- 2、编写prompt的原则与策略
- 2.1、编写清晰、具体的指令
- 2.1.1、策略一:使用分隔符清晰地表示输入的不同部分
- 2.1.2、策略二:要求一个结构化的输出
- 2.1.3、策略三:要求模型检查是否满足条件
- 2.1.4、策略四:提供少量示例
- 2.2、给模型时间去思考
- 2.2.1、策略一:指定完成任务所需的步骤
- 2.2.2、策略二:指导模型在下结论之前找出一个自己的解法
- 3、局限性
1、简介
- 随着大型语言模型(LLM)的发展,LLM 大致可以分为两种类型,即基础LLM和指令微调LLM。基础LLM也就是之前那些预训练语言模型(如GPT-1, GPT-2, GPT-3)。指令微调LLM也就是在基于已经训练好的基础LLM,然后,使用输入是指令(prompt即提示)、输出是其应该返回的结果的数据集来对其进行微调,要求它遵循这些指令。然后通常使用一种称为 RLHF(reinforcement learning from human feedback,人类反馈强化学习)的技术进行进一步改进,使系统更能够有帮助地遵循指令。因为指令调整的 LLMs 已经被训练成有益、诚实和无害的,所以与基础LLMs相比,它们更不可能输出有问题的文本,如有害输出。
- 当您使用指令微调 LLM 时,请类似于考虑向另一个人提供指令,假设它是一个聪明但不知道您任务的具体细节的人。当 LLM 无法正常工作时,有时是因为指令不够清晰。所以学好如何更好地提问,即如何做prompt工程师至关重要的】
2、编写prompt的原则与策略
2个原则:
- 1、编写清晰、具体的指令
- 2、给模型时间去思考
2.1、编写清晰、具体的指令
清晰与具体的指令将引导模型给出更准确详细的输出!
2.1.1、策略一:使用分隔符清晰地表示输入的不同部分
你可以使用任何明显的标点符号将特定的文本部分与prompt的其余部分分开,分隔符可以是:`,"",<>。这样是为了防止特定的文本与prompt冲突,导致prompt不明确。
如 输入一段 prompt 让 chatgpt 来总结:
【注:下面代码中使用 \ 来使文本适应屏幕大小以提高阅读体验,GPT 并不受 \ 的影响,但在你调用其他大模型时,需额外考虑 \ 是否会影响模型性能。】
text = f"""
你应该提供尽可能清晰、具体的指示,以表达你希望模型执行的任务。\
这将引导模型朝向所需的输出,并降低收到无关或不正确响应的可能性。\
不要将写清晰的提示与写简短的提示混淆。\
在许多情况下,更长的提示可以为模型提供更多的清晰度和上下文信息,从而导致更详细和相关的输出。
"""
# 需要总结的文本内容
prompt = f"""把用三个反引号括起来的文本总结成一句话。```{text}```"""
输出:
提供清晰具体的指示,避免无关或不正确响应,不要混淆写清晰和写简短,更长的提示可以提供更多清晰度和上下文信息,导致更详细和相关的输出。
2.1.2、策略二:要求一个结构化的输出
可以要求模型生成一个结构化的输出(如 Json、HTML 等格式),这可以使模型的输出更容易被我们解析。
prompt = f"""
请生成包括书名、作者和类别的3本虚构书籍清单,\
并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。
"""
生成如下:
{
"books": [
{
"book_id": 1,
"title": "The Shadow of the Wind",
"author": "Carlos Ruiz Zafón",
"genre": "Mystery"
},
{
"book_id": 2,
"title": "The Name of the Wind",
"author": "Patrick Rothfuss",
"genre": "Fantasy"
},
{
"book_id": 3,
"title": "The Hitchhiker's Guide to the Galaxy",
"author": "Douglas Adams",
"genre": "Science Fiction"
}
]
}
2.1.3、策略三:要求模型检查是否满足条件
如果任务做出的假设不一定满足,我们可以告诉模型先检查这些假设,如果不满足,指示并停止执行。你还可以考虑潜在的边缘情况以及模型应该如何处理它们,以避免意外的错误或结果。
下面将让chatgpt判断prompt中是否包含明确的步骤指令,如果包含则按照给定格式重新编写指令,不包含则回答未提供步骤。
- 有步骤的文本:
text_1 = f"""
泡一杯茶很容易。首先,需要把水烧开。\
在等待期间,拿一个杯子并把茶包放进去。\
一旦水足够热,就把它倒在茶包上。\
等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\
如果你愿意,可以加一些糖或牛奶调味。\
就这样,你可以享受一杯美味的茶了。
"""
prompt = f"""您将获得由三个引号括起来的文本。如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:
第一步 - ...
第二步 - …
…
第N步 - …
如果文本中不包含一系列的指令,则直接写“未提供步骤”。"
\"\"\"{text_1}\"\"\"
"""
输出:
第一步 - 把水烧开。
第二步 - 拿一个杯子并把茶包放进去。
第三步 - 把烧开的水倒在茶包上。
第四步 - 等待几分钟,让茶叶浸泡。
第五步 - 取出茶包。
第六步 - 如果你愿意,可以加一些糖或牛奶调味。
第七步 - 就这样,你可以享受一杯美味的茶了。
- 无步骤的文本:
text_2 = f"""
今天阳光明媚,鸟儿在歌唱。\
这是一个去公园散步的美好日子。\
鲜花盛开,树枝在微风中轻轻摇曳。\
人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\
这是一个完美的日子,可以在户外度过并欣赏大自然的美景。
"""
prompt = f"""
您将获得由三个引号括起来的文本。如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:
第一步 - ...
第二步 - …
…
第N步 - …
如果文本中不包含一系列的指令,则直接写“未提供步骤”。"
\"\"\"{text_2}\"\"\"
"""
输出:
未提供步骤。
2.1.4、策略四:提供少量示例
也就是gpt3里那种few-shot的方式,在要求模型执行实际任务之前,提供给它少量成功执行任务的示例
prompt = f"""
你的任务是以一致的风格回答问题。
<孩子>: 教我耐心。
<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。
<孩子>: 教我韧性。
"""
输出:
<祖父母>: 韧性就像是一棵树,它需要经历风吹雨打、寒冬酷暑,才能成长得更加坚强。在生活中,我们也需要经历各种挫折和困难,才能锻炼出韧性。记住,不要轻易放弃,坚持下去,你会发现自己变得更加坚强。
2.2、给模型时间去思考
引导模型在得出最终答案前进行一系列相关推理,指示模型花更多时间思考问题,这意味着它在任务上花费了更多的计算资源。防止模型在短时间内或用少量文字得出可能得出错误的结论。
2.2.1、策略一:指定完成任务所需的步骤
对于一些复杂的任务,给模型提供该任务的一系列步骤,有助于生成更满意的结果。
text = f"""
在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\
他们一边唱着欢乐的歌,一边往上爬,\
然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\
虽然略有些摔伤,但他们还是回到了温馨的家中。\
尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。
"""
prompt_2 = f"""
1-用一句话概括下面用<>括起来的文本。
2-将摘要翻译成英语。
3-在英语摘要中列出每个名称。
4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。
请使用以下格式:
文本:[要总结的文本]
摘要:[摘要]
翻译:[摘要的翻译]
名称:[英语摘要中的名称列表]
输出 JSON:[带有 English_summary 和 num_names 的 JSON]
Text: <{text}>
"""
输出:
摘要:兄妹杰克和吉尔在迷人的村庄里冒险,不幸摔伤后回到家中,但仍然充满冒险精神。
翻译:In a charming village, siblings Jack and Jill set out to fetch water from a mountaintop well. While climbing and singing, Jack trips on a stone and tumbles down the mountain, with Jill following closely behind. Despite some bruises, they make it back home safely. Their adventurous spirit remains undiminished as they continue to explore with joy.
名称:Jack,Jill
输出 JSON:{"English_summary": "In a charming village, siblings Jack and Jill set out to fetch water from a mountaintop well. While climbing and singing, Jack trips on a stone and tumbles down the mountain, with Jill following closely behind. Despite some bruises, they make it back home safely. Their adventurous spirit remains undiminished as they continue to explore with joy.", "num_names": 2}
2.2.2、策略二:指导模型在下结论之前找出一个自己的解法
有时候你直接问模型,比如:“判断我的解决方案是否正确,现在要解决一个xx问题,我的解决方案是xx。”;模型很有可能被我的解决方案误导为是正确的,但实际上你的解决方案是错的。这时候如果先让模型自己先找出一个解决方案,再和我的解决方案对比,这样得出的解决方案才更可能是经过模型思考的。
- 模型犯错例子:
prompt = f"""
判断学生的解决方案是否正确。
问题:
我正在建造一个太阳能发电站,需要帮助计算财务。
土地费用为 100美元/平方英尺
我可以以 250美元/平方英尺的价格购买太阳能电池板
我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元
作为平方英尺数的函数,首年运营的总费用是多少。
学生的解决方案:
设x为发电站的大小,单位为平方英尺。
费用:
土地费用:100x
太阳能电池板费用:250x
维护费用:100,000美元+100x
总费用:100x+250x+100,000美元+100x=450x+100,000美元
"""
输出:
学生的解决方案是正确的。
- 模型回答正确例子:
prompt = f"""
请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:
步骤:
首先,自己解决问题。
然后将你的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。在自己完成问题之前,请勿决定学生的解决方案是否正确。
使用以下格式:
问题:问题文本
学生的解决方案:学生的解决方案文本
实际解决方案和步骤:实际解决方案和步骤文本
学生的解决方案和实际解决方案是否相同:是或否
学生的成绩:正确或不正确
问题:
我正在建造一个太阳能发电站,需要帮助计算财务。
- 土地费用为每平方英尺100美元
- 我可以以每平方英尺250美元的价格购买太阳能电池板
- 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元
作为平方英尺数的函数,首年运营的总费用是多少。
学生的解决方案:
设x为发电站的大小,单位为平方英尺。
费用:
1. 土地费用:100x
2. 太阳能电池板费用:250x
3. 维护费用:100,000+100x
总费用:100x+250x+100,000+100x=450x+100,000
实际解决方案和步骤:
"""
输出:
正确的解决方案和步骤:
1. 计算土地费用:100美元/平方英尺 * x平方英尺 = 100x美元
2. 计算太阳能电池板费用:250美元/平方英尺 * x平方英尺 = 250x美元
3. 计算维护费用:10万美元 + 10美元/平方英尺 * x平方英尺 = 10万美元 + 10x美元
4. 计算总费用:100x美元 + 250x美元 + 10万美元 + 10x美元 = 360x + 10万美元
学生的解决方案和实际解决方案是否相同:否
学生的成绩:不正确
3、局限性
- 模型偶尔会一本正经地胡说八道,也就是会生成一些看似真实实则并不正确或存在的虚假内容,又称为 “hallucination” 即幻觉。
- 所以学好构建prompt的技巧有利于在构建自己的LLM应用程序时避免这种情况。
- 在你希望模型根据文本生成答案的情况下,另一种减少幻觉的策略是先要求模型找到文本中的任何相关引用,然后要求它使用这些引用来回答问题,这种追溯源文档的方法通常对减少幻觉非常有帮助。
参考链接:
[1] OpenAI
[2] 吴恩达老师的:DeepLearning.AI
[3] DataWhale
[4] https://learn.deeplearning.ai/