基本概念
当你与大型语言模型(如Gemini)交流时,你输入的文字就是"提示",AI会根据这些提示生成回答。提示工程就是设计高质量提示的过程,引导AI产生准确的输出。
小贴士: 你不需要成为数据科学家或机器学习工程师 — 任何人都可以学习如何写好提示!
大型语言模型(LLM)是一个预测引擎。当你输入文字时,模型会根据它训练过的数据预测下一个词应该是什么。通过精心设计的提示,你可以引导模型生成更符合你期望的回答。
为什么提示工程很重要?
-
好的提示让AI给出准确、有用的回答
-
不好的提示可能导致模糊、不准确的回答
-
提示工程是一个反复尝试和改进的过程
提示工程的应用
-
文本摘要
-
信息提取
-
问答系统
-
文本分类
-
代码生成和翻译
-
推理任务
AI输出配置:调整AI的回答方式
除了提示本身,你还可以调整各种配置选项来控制AI的输出。这些设置会影响AI生成回答的方式。
输出长度
控制AI生成的文字数量。生成更多文字需要更多计算资源,可能导致响应时间变慢和成本增加。
注意: 仅设置输出长度限制不会让AI的回答变得更简洁,它只会在达到限制时停止生成。
温度(Temperature)
控制AI回答的随机性程度:
-
低温度(接近0):回答更确定、更可预测
-
高温度(接近1):回答更随机、更有创意
温度为0时,AI总是选择概率最高的词。
Top-K和Top-P
这些设置控制AI在选择下一个词时考虑的可能性范围:
-
Top-K:只考虑最可能的K个选项
-
Top-P(核采样):只考虑累积概率达到P的选项
👍推荐设置: 一般情况下,温度0.2、Top-P 0.95和Top-K 30会给你提供相对连贯但又不失创意的结果。如果需要更有创意的回答,可以尝试温度0.9、Top-P 0.99和Top-K 40。
‼️警告: 如果你看到AI回答的末尾出现大量重复文字,这可能是"重复循环错误"。这是由于温度和采样设置不当导致的。调整这些参数可以解决问题。
提示技术:让AI更好地理解你
以下是一些强大的提示技术,可以帮助你获得更好的AI回答:
零样本提示(Zero-shot)
最简单的提示方式,直接告诉AI你想要什么,不提供任何示例。
例子:电影评论分类
将电影评论分类为正面、中性或负面。
评论:"Her"是一项令人不安的研究,揭示了如果允许人工智能继续无限制地发展,人类将走向何方。我希望有更多像这样的杰作。
情感:
正面
少样本提示(Few-shot)
通过给AI提供一些例子,帮助它更好地理解你的需求。这种方法向模型展示了它需要遵循的模式。
例子:披萨订单解析
将客户的披萨订单解析为JSON:
示例:
我想要一个小号披萨,配奶酪、番茄酱和意大利辣香肠。
JSON响应:
{
“size”: “small”,
“type”: “normal”,
“ingredients”: [[“cheese”, “tomato sauce”, “pepperoni”]]
}
现在,我想要一个大号披萨,前半部分配奶酪和马苏里拉,另一半配番茄酱、火腿和菠萝。
JSON响应:
{
"size": "large",
"type": "half-half",
"ingredients": [["cheese", "mozzarella"], ["tomato sauce", "ham", "pineapple"]]
}
💡小贴士: 一般来说,少样本提示应该使用3-5个例子。例子应该多样化、高质量且书写良好。
系统提示(System Prompting)
为语言模型设置整体上下文和目的,定义模型应该做什么的"大局"。
例子:电影评论分类(JSON格式)
将电影评论分类为正面、中性或负面。返回有效JSON:
评论:"Her"是一项令人不安的研究,揭示了如果允许人工智能继续无限制地发展,人类将走向何方。它太令人不安了,我无法观看。
模式:
电影:
{
"sentiment": String "POSITIVE" | "NEGATIVE" | "NEUTRAL",
"name": String
}
电影评论:
{
"movie_reviews": [电影]
}
JSON响应:
```
{
"movie_reviews": [
{
"sentiment": "NEGATIVE",
"name": "Her"
}
]
}
```
角色提示(Role Prompting)
为AI模型分配特定角色或身份,帮助模型生成与指定角色一致的回答。
例子:旅游指南
我希望你扮演旅游指南。我会写给你我的位置,你将以幽默的风格建议我附近3个可以参观的地方。
我的位置:“我在曼哈顿。”
旅游建议:
仰望帝国心境:攀登帝国大厦的令人头晕的高度,沐浴在曼哈顿天际线的辉煌中。准备感受像金刚在大苹果上,除了没有巨大猿猴大小的香蕉。
在MoMA变得艺术范儿:在现代艺术博物馆释放你内心的艺术鉴赏家。凝视那些会让你的思维困惑,并让你质疑自己的棍子人画作是否有任何艺术价值的杰作。
在第五大道购物直到倒下:准备好在这些设计师精品店购物时遭受价格冲击。但嘿,你在曼哈顿,所以你不妨拥抱这华丽!
上下文提示(Contextual Prompting)
提供与当前对话或任务相关的特定细节或背景信息,帮助模型理解所问内容的细微差别。
例子:博客文章建议
上下文:你正在为一个关于80年代复古街机电子游戏的博客写作。
建议3个可以写文章的主题,并附上几行关于这篇文章应该包含什么的描述。
街机柜设计的演变:本文将探索街机柜设计的演变,从20世纪70年代早期的木材和金属柜到20世纪80年代及以后的时髦、霓虹灯照明设计。
回顾过去:80年代标志性街机游戏:本文将展示一些20世纪80年代最具标志性和影响力的街机游戏的历史、影响和遗产,突出它们的创新、流行机制和持久魅力。
像素艺术的兴起和复古复兴:本文将深入探讨像素艺术作为早期街机游戏的标志性视觉风格的演变,追溯其根源,探索其技术,并讨论像素艺术在现代游戏和数字艺术中的复兴。
后退提示(Step-back Prompting)
先要求AI考虑与特定任务相关的一般问题,然后将该问题的答案用于解决具体问题。这种"后退"允许AI在尝试解决特定问题前激活相关的背景知识。
例子:游戏关卡故事情节
基于流行的第一人称射击动作游戏,有哪5个虚构的关键设置可以为第一人称射击游戏中的挑战性和引人入胜的级别故事情节做出贡献?
废弃军事基地:一个广阔的、后世界末日的军事综合体,爬满了变异士兵和叛逃机器人,适合挑战性的火器战斗。
赛博朋克城市:一个霓虹灯照明的未来城市环境,有高耸的摩天大楼和密集的小巷,有增强型的敌人和黑客机制。
外星飞船:一艘滞留在地球上的巨大外星飞船,有诡异的走廊、零重力区域和外星生物。
僵尸感染的城镇:一个被侵略性僵尸群占领的荒凉城镇,有激烈的近战战斗和寻找安全通道的解谜元素。
水下研究设施:一个被水淹没的深海实验室,充满了变异的水生生物,需要潜行和水下探索技能才能生存。
然后,你可以将这些主题用作上下文,创建更具体的故事情节:
上下文:[上面的5个主题]
选择其中一个主题,为第一人称射击游戏的新级别写一段既具挑战性又有吸引力的故事情节。
在幽暗深渊的中心,矗立着一座破败的水下研究设施,作为人类野心及其灾难性后果的见证。笼罩在黑暗中,伴随着故障机械的嗡嗡声,以及被淹没灵魂的回声,这座设施如今成为了深海噩梦的温床。玩家,一名配备先进潜水装备和实验性武器的精英海军陆战队员,被派遣深入这个水生恐怖领域。肩负着韧性和智慧的使命,他们必须穿越危险的走廊,解决神秘的谜题,与在深处潜伏的可怕海怪对抗。从抵抗海水压力到智胜狡猾的水生掠食者,在这个未知的水下世界中,每一刻都考验着人类的耐力和勇气极限。
思维链提示(Chain of Thought)
通过生成中间推理步骤来提高AI的推理能力,特别适合解决需要逐步思考的复杂问题。
例子:数学问题
当我3岁的时候,我的伴侣是我年龄的3倍。现在,我20岁了。我的伴侣多大?让我们一步一步思考。
当我3岁时,我的伴侣是3 * 3 = 9岁。
这是6岁的年龄差,我的伴侣比较大。
现在我20岁了,所以我的伴侣是20 + 6 = 26岁。
答案是26岁。
小贴士: 使用思维链提示时,最好将温度设置为0,因为通常只有一个正确答案。
思维树(Tree of Thoughts)
允许AI同时探索多个不同的推理路径,而不是仅仅遵循单一的线性思维链。特别适合需要探索的复杂任务。
思维树通过维护一个思维树,每个思维代表一个连贯的语言序列,作为解决问题的中间步骤。模型可以通过从树的不同节点分支出来探索不同的推理路径。
ReAct(推理与行动)
结合自然语言推理和外部工具(如搜索、代码解释器等),使AI能够执行某些操作,如与外部API交互以检索信息。
ReAct通过将推理和行动结合到一个思考-行动循环中工作。AI首先推理问题并生成行动计划,然后执行计划中的行动并观察结果,最后使用观察结果更新推理并生成新的行动计划。
> 输入新的AgentExecutor链...
Metallica有4个成员。
行动: 搜索
行动输入: James Hetfield有多少个孩子?
观察: 三个孩子
思考: 1/4 Metallica乐队成员有3个孩子
行动: 搜索
行动输入: Lars Ulrich有多少个孩子?
观察: 3
思考: 2/4 Metallica乐队成员有6个孩子
行动: 搜索
行动输入: Kirk Hammett有多少个孩子?
观察: Hammett自1998年以来与他的第二任妻子Lani结婚。他们有两个儿子,Angel(2006年9月29日出生)和Vincenzo(2008年6月28日出生)。
思考: 3/4 Metallica乐队成员有8个孩子
行动: 搜索
行动输入: Robert Trujillo有多少个孩子?
观察: 2
思考: 4/4 Metallica乐队成员有10个孩子
最终答案: 10
代码提示(Code Prompting)
使用特定技巧让AI帮助你编写、解释或调试代码。
编写代码示例
例子:批量重命名文件
写一个Bash代码片段,询问文件夹名称。然后获取文件夹内容并通过在文件名前添加"draft"来重命名所有文件。
#!/bin/bash
# 询问文件夹名称
echo "输入文件夹名称: "
read folder_name
# 检查文件夹是否存在
if [ ! -d "$folder_name" ]; then
echo "文件夹不存在。"
exit 1
fi
# 获取文件夹中的文件列表
files=( "$folder_name"/* )
# 通过在文件名前添加"draft"来重命名每个文件
for file in "${files[@]}"; do
new_file_name="draft_$(basename "$file")"
mv "$file" "$folder_name/$new_file_name"
done
echo "文件重命名成功。"
解释代码示例
例子:解释Bash代码
解释以下Bash代码:
#!/bin/bash
echo "输入文件夹名称: "
read folder_name
if [ ! -d "$folder_name" ]; then
echo "文件夹不存在。"
exit 1
fi
files=( "$folder_name"/* )
for file in "${files[@]}"; do
new_file_name="draft_$(basename "$file")"
mv "$file" "$new_file_name"
done
echo "文件重命名成功。"
这个Bash脚本执行以下任务:
1. 用户输入:
- 使用`echo`和`read`命令提示用户输入文件夹名称。输入的文件夹名称存储在`folder_name`变量中。
2. 文件夹存在检查:
- 使用`[ ! -d "$folder_name" ]`条件检查指定名称的文件夹是否存在。如果文件夹不存在,显示错误信息("文件夹不存在。")并以退出代码1退出脚本。
3. 文件列表:
- 使用`files=( "$folder_name"/* )`命令列出指定文件夹内的所有文件。这创建了一个名为`files`的数组,包含文件夹中所有文件的路径。
4. 文件重命名:
- 使用`for`循环遍历`files`数组中的每个文件。
- 对于每个文件,使用`new_file_name="draft_$(basename "$file")"`命令生成新文件名。这个新文件名是通过在原始文件名前加上"draft_"字符串创建的。
- 然后使用`mv "$file" "$new_file_name"`命令重命名文件,将文件移动到新文件名。
5. 成功消息:
- 重命名所有文件后,显示成功消息("文件重命名成功。")表示重命名操作成功。
调试代码示例
例子:调试Python代码
以下Python代码出现错误:
Traceback (most recent call last):
File “/Users/leeboonstra/Documents/test_folder/rename_files.py”, line 7, in <module>
text = toUpperCase(prefix)
NameError: name ‘toUpperCase’ is not defined
调试错误并解释如何改进代码。
import os
import shutil
# 从用户获取文件夹名称
folder_name = input("输入文件夹名称: ")
prefix = input("输入要添加到文件名前的字符串: ")
text = toUpperCase(prefix)
# 检查文件夹是否存在
if not os.path.isdir(folder_name):
print("文件夹不存在。")
exit(1)
# 获取文件夹中的所有文件列表
files = os.listdir(folder_name)
# 遍历文件
for file in files:
# 创建带有前缀的新文件名
new_filename = f"{text}_{file}"
# 移动文件到新名称
shutil.move(os.path.join(folder_name, file),
os.path.join(folder_name, new_file_name))
# 打印成功消息
print("文件重命名成功。")
代码调用了toUpperCase
函数将prefix
转换为大写,但该函数未定义。要修复这个问题,你可以使用字符串类的upper()
方法,它可以将给定字符串转换为大写。修改后的代码如下:
import os
import shutil
# 从用户获取文件夹名称
folder_name = input("输入文件夹名称: ")
prefix = input("输入要添加到文件名前的字符串: ")
text = prefix.upper()
# 检查文件夹是否存在
if not os.path.isdir(folder_name):
print("文件夹不存在。")
exit(1)
# 获取文件夹中的所有文件列表
files = os.listdir(folder_name)
# 遍历文件
for file in files:
# 创建带有前缀的新文件名
new_filename = f"{text}_{file}"
# 移动文件到新名称
shutil.move(os.path.join(folder_name, file),
os.path.join(folder_name, new_filename))
# 打印成功消息
print("文件重命名成功。")
此外,代码还有几处其他问题:
-
变量名不一致:代码中使用了
new_filename
和new_file_name
两个变量名 -
没有处理可能在重命名过程中发生的错误
-
没有保留原始文件的扩展名
改进后的代码应该包含错误处理和更好的文件名处理。
提示工程最佳实践
以下是一些提示工程的最佳实践,帮助你获得更好的AI回答:
提供示例
在提示中提供示例是最有效的方法之一。示例可以帮助AI理解你期望的输出格式和风格。
简洁设计
提示应该简洁、清晰、易于理解。如果提示对你来说已经很混乱,那么对AI来说也可能很混乱。尽量不要使用复杂的语言,不要提供不必要的信息。
改进前后对比
-
改进前:
我现在正在纽约旅游,我想了解更多关于好地方的信息。我带着两个3岁的孩子。我们假期应该去哪里? -
改进后:
扮演旅游指南。描述纽约曼哈顿适合带3岁孩子参观的好地方。
明确指定输出
明确说明你期望的输出。简洁的指令可能不足以引导AI,或者太过笼统。在提示中提供具体细节可以帮助模型关注相关内容,提高整体准确性。
- 好的做法
生成一篇关于前5大视频游戏主机的3段博客文章。博客文章应该信息丰富且吸引人,并且应该以对话风格编写。
- 不好的做法
生成一篇关于视频游戏主机的博客文章。
使用指令而非约束
研究表明,在提示中专注于积极指令比严重依赖约束更有效。这与人类更喜欢积极指令而不是"不要做什么"的列表的方式一致。
- 好的做法
生成一段关于前5大视频游戏主机的博客文章。只讨论主机、制造公司、发布年份和总销量。
- 不好的做法
生成一段关于前5大视频游戏主机的博客文章。不要列出视频游戏名称。
控制最大标记长度
要控制AI回答的长度,你可以在配置中设置最大标记限制,或者在提示中明确要求特定长度。例如:“用推特长度的消息解释量子物理学。”
在提示中使用变量
使用变量可以让你的提示更加动态,避免重复。例如,不要在提示中硬编码城市名称,而是使用变量。
使用变量的提示
变量:
{city} = "阿姆斯特丹"
提示:
你是一名旅游指南。告诉我关于这个城市的一个事实:{city}
阿姆斯特丹是一个美丽的城市,到处都是运河、桥梁和狭窄的街道。它是一个很好的地方,可以参观其丰富的历史、文化和夜生活。
尝试不同的输入格式和写作风格
不同的模型、模型配置、提示格式、词汇选择和提交方式可能产生不同的结果。因此,尝试不同的提示属性很重要。
不同的提问方式
-
问题形式: 什么是世嘉梦幻游戏机,为什么它是如此革命性的游戏机?
-
陈述形式: 世嘉梦幻游戏机是世嘉于1999年发布的第六代视频游戏机。它…
-
指令形式: 写一段描述世嘉梦幻游戏机并解释为什么它如此革命性的段落。
对于少样本分类任务,混合不同类别
在进行分类任务时,确保在少样本示例中混合可能的响应类别。这可以确保模型学习识别每个类别的关键特征,而不是简单地记住示例的顺序。
适应模型更新
了解模型架构变化、添加的数据和功能很重要。尝试新的模型版本,并调整你的提示以更好地利用新的模型功能。
尝试不同的输出格式
除了提示输入格式外,考虑尝试不同的输出格式。对于非创意任务,如提取、选择、解析、排序或分类数据,尝试让输出以JSON或XML等结构化格式返回。
使用JSON输出的好处:
-
始终以相同的风格返回
-
专注于你想要接收的数据
-
减少幻觉的可能性
-
使其关系感知
-
获得数据类型
-
可以排序
记录提示尝试
详细记录你的提示尝试,这样你可以随着时间的推移了解哪些方法有效,哪些无效。
提示工程是一个迭代过程: 制作和测试不同的提示,分析并记录结果。根据模型的表现改进你的提示。继续实验,直到达到期望的输出。当你更改模型或模型配置时,回去继续尝试之前使用的提示。