前言:
上一章,我们介绍了大模型的理论知识,类型和在RA中使用的情况和效果。
本章,我们介绍如何让RA生成的最终内容更贴合我们要的内容。
提示词是非常影响最终结果的一个技术细节内容,通常正向提示词比反向提示词作用大很多。
并且提示词的各种使用技巧,对于控制AI最后生成的效果,时间,等都有更多的影响力。学习好这些内容绝对对于掌握AIGC能力至关重要。
知识点:
- 关键字/提示词的使用细节
- 关键字/提示词的使用原则
总体感受:
实际上我们认为,提示词,针对不同的人,不同的要求,是完全不同的。但是一般的,我们有一些共性的需求,这里就针对这种共性,整理出来一些公共的内容或者规范。
提高图像质量的 prompt
prompt | 描述 |
---|---|
HDR, UHD, 8K | (HDR、UHD、4K、8K和64K)这样的质量词可以带来巨大的差异提升照片的质量 |
best quality | 最佳质量 |
masterpiece | 杰作 |
Highly detailed | 画出更多详细的细节 |
Studio lighting | 添加演播室的灯光,可以为图像添加一些漂亮的纹理 |
ultra-fine painting | 超精细绘画 |
sharp focus | 聚焦清晰 |
physically-based rendering | 基于物理渲染 |
extreme detail description | 极其详细的刻画 |
Professional | 加入该词可以大大改善图像的色彩对比和细节 |
Vivid Colors | 给图片添加鲜艳的色彩,可以为你的图像增添活力 |
Bokeh | 虚化模糊了背景,突出了主体,像 iPhone 的人像模式 |
(EOS R8, 50mm, F1.2, 8K, RAW photo:1.2) | 摄影师对相机设置的描述 |
High resolution scan | 让你的照片具有老照片的样子赋予年代感 |
Sketch | 素描 |
Painting | 绘画 |
艺术风格代表的 prompt
加入对应类型画家的风格,提升我们的照片效果。
艺术风格 | 艺术家 |
---|---|
肖像画(Portraits) | Derek Gores, Miles Aldridge, Jean Baptiste-Carpeaux, Anne-Louis Girodet |
风景画(Landscape) | Alejandro Bursido, Jacques-Laurent Agasse, Andreas Achenbach, Cuno Amiet |
恐怖画(Horror) | H.R.Giger, Tim Burton, Andy Fairhurst, Zdzislaw Beksinski |
动漫画(Anime) | Makoto Shinkai, Katsuhiro Otomo, Masashi Kishimoto, Kentaro Miura |
科幻画(Sci-fi) | Chesley Bonestell, Karel Thole, Jim Burns, Enki Bilal |
摄影(Photography) | Ansel Adams, Ray Earnes, Peter Kemp, Ruth Bernhard |
概念艺术家(视频游戏)(Concept artists (video game)) | Emerson Tung, Shaddy Safadi, Kentaro Miura |
常用的反向prompt
negative prompt | 描述 |
---|---|
mutated hands and fingers | 变异的手和手指 |
deformed | 畸形的 |
bad anatomy | 解剖不良 |
disfigured | 毁容 |
poorly drawn face | 脸部画得不好 |
mutated | 变异的 |
extra limb | 多余的肢体 |
ugly | 丑陋 |
poorly drawn hands | 手部画得很差 |
missing limb | 缺少的肢体 |
floating limbs | 漂浮的四肢 |
disconnected limbs | 肢体不连贯 |
malformed hands | 畸形的手 |
out of focus | 脱离焦点 |
long neck | 长颈 |
long body | 身体长 |
下面的内容是我们想要尝试设计更好的关键字的基础上的强理论知识, 建议学者在一定的体验尝试基础上再学习。
此时我们可以直接在RA上多尝试几种不同的关键字内容和效果。
比如一般标准的正向提示词:
Girl,solo,eizag_t_v1-600:1,long loose hair,dark hair,black eyes,lighter irises,realistic irises,detailed irises,detailed face,detailed eyes,detailed lips),closeup,portrait,sharp focus,rim lightning,dark studio:1.2,realistic and hyper detailed jewelry (shiny skin:0.9),standing,(masterpiece:1.5, high quality:1.5, beautiful and delicate, hyper realistic photography, amazing, photoshoot, 8k, realistic, detailed background,
反向提示词:
disfigured,deformed,tattoo,double face,broken legs,old,(worst quality:2),(low quality:2),(normal quality:2),lowres,watermark,
更多的理论知识: 【高级内容,可能需要一定技术背景】
两个基本原则
- 编写清晰、具体的但不简短的指令
- 给模型时间思考
原则一:编写清晰、具体的但不简短的指令
你应该通过提供尽可能清晰和具体的指令来表达你希望模型执行的操作。
这将引导模型给出正确的输出,并降低你得到无关或不正确响应的可能性。
清晰的指令不意味着必须简短,在许多情况下,更长的 Prompt 实际上更清晰,且提供了更多上下文,也就可能产生更详细更相关的输出。
使用分隔符清晰地表示输入的不同部分
分隔符可以是:“`,””,<>,:,<tag> </tag>等。
你可以使用任何明显的标点符号将特定的文本部分与 Prompt 的其余部分分开。
标记的形式不限,只需要让模型明确知道这是一个单独部分。
使用分隔符可以有效避免提示词注入( Prompt injection )。
提示词注入是指如果允许用户将某些输入添加到(开发者预定义的) Prompt 中,则所提供的指令可能会与开发者想要执行的操作相冲突,从而使 LLM 遵循用户输入的指令,而非执行开发者预期的操作。即输入里面可能包含其他指令,会覆盖掉你的指令。对此,使用分隔符是一个不错的策略。
在以下的例子中,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 “` 来作为分隔符。
重要解释: text对象是输入的文本内容, prompt是准备使用到的关键字,针对输入的text进行再处理用。response是处理后的输出内容
text = f"""
你应该提供尽可能清晰、具体的指示,以表达你希望模型执行的任务。\
这将引导模型朝向所需的输出,并降低收到无关或不正确响应的可能性。\
不要将写清晰的提示词与写简短的提示词混淆。\
在许多情况下,更长的提示词可以为模型提供更多的清晰度和上下文信息,从而导致更详细和相关的输出。
"""
# 需要总结的文本内容
prompt = f"""
请你把以下文本总结成一句话:
((({text})))
"""
# 指令内容,使用 ``` 来分隔指令和待总结的内容
response = get_completion(prompt)
print(response)
为了得到所需的输出,应该提供清晰、具体的指示,避免简短的提示词,更长的提示词可以提供更多的清晰度和上下文信息。
寻求结构化的输出
输出可以是 JSON、HTML 等格式。
第二个策略是要求生成一个结构化的输出,这可以使模型的输出更容易被我们解析,例如,你可以在 Python 中将其读入字典或列表中。
在以下示例中,我们要求文心一言生成三本书的标题、作者和类别,并要求文心一言以 Json 的格式返回给我们,为便于解析,我们指定了 JSON 的键。
prompt = f"""
请生成三本虚构中文书籍清单,```包括书名、作者和类别```,\
并以 JSON 格式直接输出给我,内容应该包含以下键:<book_id>、<title>、<author>、<genre>。
不要输出无关内容。
"""
response = get_completion(prompt)
print(response)
```json { "books": [ { "book_id": 1, "title": "星际穿越", "author": "刘慈欣", "genre": "科幻" }, { "book_id": 2, "title": "围城", "author": "钱钟书", "genre": "文学" }, { "book_id": 3, "title": "明朝那些事儿", "author": "当年明月", "genre": "历史" } ] }```
要求模型检查是否满足条件
如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。你还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。
在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答“未提供步骤”。
In [5]
# 满足条件的输入(text中提供了步骤)
text_1 = f"""
泡一杯茶很容易。首先,需要把水烧开。\
在等待期间,拿一个杯子并把茶包放进去。\
一旦水足够热,就把它倒在茶包上。\
等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\
如果您愿意,可以加一些糖或牛奶调味。\
就这样,您可以享受一杯美味的茶了。
"""
prompt = f"""
我会给你一段文本。\
如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:
第一步 - ...
第二步 - ...
...
第<N>步 - ...
如果文本中不包含一系列的指令,则直接输出“未提供步骤”。"
\"\"\"{text_1}\"\"\"
"""
response = get_completion(prompt)
print("Text 1 的总结:")
print(response)
Text 1 的总结: 第一步 - 把水烧开。 第二步 - 在等待期间,拿一个杯子并把茶包放进去。 第三步 - 一旦水足够热,就把它倒在茶包上。 第四步 - 等待一会儿,让茶叶浸泡。 第五步 - 几分钟后,取出茶包。 第六步 - 如果您愿意,可以加一些糖或牛奶调味。
In [6]
# 不满足条件的输入(text中未提供预期指令)
text_2 = f"""
今天阳光明媚,鸟儿在歌唱。\
这是一个去公园散步的美好日子。\
鲜花盛开,树枝在微风中轻轻摇曳。\
人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\
这是一个完美的日子,可以在户外度过并欣赏大自然的美景。
"""
prompt = f"""
我会给你一段文本。\
如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:
第一步 - ...
第二步 - ...
...
第<N>步 - ...
如果文本中不包含一系列的指令,则直接输出“未提供步骤”。"
\"\"\"{text_2}\"\"\"
"""
response = get_completion(prompt)
print("Text 2 的总结:")
print(response)
Text 2 的总结: 未提供步骤。
提供少量示例(少样本提示词,Few-shot prompting)
即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例。
例如,在以下的示例中,我们告诉模型其任务是以一致的风格回答问题,并先给它一个孩子和外婆之间的对话的例子。孩子说,“请教我何为耐心”,外婆用下述风格的隐喻来回答。由于我们已经告诉模型要以一致的语气回答,因此现在我们问“请教我何为韧性”,由于模型已经有了这个少样本示例( few-shot example )
,它将以类似的语气回答下一个任务。
In [7]
prompt = f"""
仿照<外婆>的对话风格续写对话:
```
<孩子>: 教我耐心。
<外婆>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。
<孩子>: 教我韧性。```
"""
response = get_completion(prompt)
print(response)
<孩子>: 教我韧性。 <外婆>: 你看那些参天的大树,它们扎根深山,风雨无阻,它们的生命力坚韧而持久。就像我们的生活,无论遭遇多少困难和挫折,我们都不能放弃,而要有勇气坚持下去。 <孩子>: 教我坚持。 <外婆>: 你看那千里之堤,它如何抵挡住狂风暴雨,就如同我们在面对困难时如何坚守自己的信念和目标。即使在最艰难的时候,我们也不能放弃,要坚信只要坚持下去,总会有希望。 <孩子>: 教我毅力。
原则二 给模型时间去思考
如果你发现模型推理过程过于匆忙,导致得出了错误的结论,那么你应该尝试重新构思 Prompt ,要求模型在提供最终答案之前开展思维链,或进行一系列相关推理(a chain or series of relevant reasoning)。
换句话说,如果你给模型一个在短时间内或用少量文字无法完成的复杂任务,它的输出结果就容易出错。这种情况对人来说也是类似:如果你要求某人完成复杂的数学问题,又不给足够时间计算出答案,他们也可能会犯错误。
因此,在这些情况下,你应该指示模型花更多时间思考问题,让它在任务上花费更多计算资源。
指定完成任务所需的步骤
这个示例内容就非常的多了。请耐心看完
接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果。
首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作:首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成英语。第三,在英语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:英语摘要和人名个数。要求输出以换行符分隔。
In [10]
text = f"""
在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶的井里打水。\
他们一边唱着欢乐的歌,一边往上爬,\
然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\
虽然略有些摔伤,但他们还是回到了温馨的家中。\
尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。
"""
# example 1
prompt_1 = f"""
执行以下操作:
1. 用一句话概括下面的文本。
2. 把概括后的文本翻译成英文摘要。
3. 在英文摘要中列出每个人名。
4. 输出一个 JSON 文本,其中包含以下键:<english_summary>,<num_names>。
文本:
```{text}```
"""
response = get_completion(prompt_1)
print("prompt 1:")
print(response)
prompt 1: 2. 在一个迷人的村庄里,杰克和吉尔兄妹去山上打水。不幸的是,他们滚了下来,但仍然回到了家,并继续探索。 3. 兄妹俩:杰克和吉尔 4. ```json { "english_summary": "In a charming village, siblings Jack and Jill set out to fetch water from a well at the top of a mountain. Although they sustained some injuries, they still returned home and continued to explore.", "num_names": 2 } ```
上述输出仍然存在一定问题,例如,漏掉了 JSON 文本输出的步骤。
因此,我们将Prompt加以改进,该 Prompt 前半部分不变,同时确切指定了输出的格式。
In [11]
prompt_2 = f"""
执行以下操作:
1. 用一句话概括下面的文本。
2. 把概括后的文本翻译成英文摘要。
3. 在英文摘要中列出每个人名。
4. 输出一个 JSON 文本,其中包含以下键:<english_summary>,<num_names>。
请使用以下格式输出:
文本:<要总结的文本>
摘要:<摘要>
翻译:<摘要的翻译>
名称:<英语摘要中的名称列表>
输出 JSON:<带有 english_summary 和 num_names 的 JSON>
文本: <{text}>
"""
response = get_completion(prompt_2)
print("\nprompt 2:")
print(response)
prompt 2: 文本:兄妹杰克和吉尔去山顶打水,途中遭遇不幸滚下山,尽管受伤却依然乐观回家并继续探索。 摘要:兄妹杰克和吉尔去山顶打水,途中遭遇不幸滚下山,受伤回家,但仍然保持乐观并继续探索。 翻译:Sibling Jack and Jill went to fetch water from a well at the top of a hill, but unfortunately Jack stumbled on a rock and rolled down the hill, followed by Jill. Although they were slightly injured, they still returned home with a positive attitude and continued to explore. 名称:Jack, Jill 输出 JSON:{"english_summary": "Sibling Jack and Jill went to fetch water from a well at the top of a hill, but unfortunately Jack stumbled on a rock and rolled down the hill, followed by Jill. Although they were slightly injured, they still returned home with a positive attitude and continued to explore.", "num_names": 2}
指导模型在下结论之前找出一个自己的解法
明确地指引模型在匆匆做决策之前,要自己思考出一份解决方案。有时这样会得到更好的结果。这与之前所述思想类似,即给模型时间思考。
接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确:
In [12]
prompt = f"""
判断学生的解决方案是否正确。
问题:
我正在建造一个太阳能发电站,需要帮助计算财务。
土地费用为 100美元/平方英尺
我可以以 250美元/平方英尺的价格购买太阳能电池板
我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元
作为平方英尺数的函数,首年运营的总费用是多少。
学生的解决方案:
设x为发电站的大小,单位为平方英尺。
费用:
土地费用:100x
太阳能电池板费用:250x
维护费用:100,000美元+100x
总费用:100x+250x+100,000美元+100x=450x+100,000美元
"""
response = get_completion(prompt)
print(response)
学生的解决方案是正确的。 在这个问题中,需要计算首年运营的总费用,其中包括土地费用、太阳能电池板费用和维护费用。学生的解决方案正确地列出了这些费用,并计算了它们的总和。 具体来说,学生的解决方案中: * 土地费用为 100x,因为每平方英尺的土地费用是100美元。 * 太阳能电池板费用为 250x,因为每平方英尺的太阳能电池板费用是250美元。 * 维护费用为首年维护合同费用10万美元,再加上每平方英尺10美元的费用,即100,000美元+100x。 * 总费用为土地费用+太阳能电池板费用+维护费用,即100x+250x+100,000美元+100x=450x+100,000美元。 因此,学生的解决方案是正确的。
但是注意,学生的解决方案实际上是错误的。(维护费用项100x应为10x,总费用450x应为360x)
我们可以通过指导模型先自行找出一个解法来解决这个问题。
在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。
In [13]
prompt = f"""
问题:我正在建造一个太阳能发电站,需要帮助计算财务。
- 土地费用为每平方英尺 100 美元
- 我可以以每平方英尺 250 美元的价格购买太阳能电池板
- 我已经谈判好了维护合同,每年需要支付固定的 10 万美元,并额外支付每平方英尺 10 美元;
```作为平方英尺数的函数,首年运营的总费用是多少?```
学生的解决方案:
设 x 为发电站的大小,单位为平方英尺。
费用:
1. 土地费用:100x 美元
2. 太阳能电池板费用:250x 美元
3. 维护费用:100,000 + 100x = 10 万美元 + 10x 美元
总费用:100x 美元 + 250x 美元 + 10 万美元 + 100x 美元 = 450x + 10 万美元
请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:
步骤:
1. 首先,自己解决问题。
2. 然后将你的解决方案与学生的解决方案进行比较,对比计算得到的总费用与学生计算的总费用是否一致,并评估学生的解决方案是否正确。
3. 在自己完成问题之前,```请勿决定学生的解决方案是否正确```。
使用以下格式:
```
问题:问题文本
学生的解决方案:学生的解决方案文本
实际解决方案和步骤:实际解决方案和步骤文本
学生计算的总费用:学生计算得到的总费用
实际计算的总费用:实际计算出的总费用
学生计算的费用和实际计算的费用是否相同:是或否
学生的解决方案和实际解决方案是否相同:是或否
学生的成绩:正确或不正确
实际解决方案和步骤:
````
"""
response = get_completion(prompt)
print(response)
问题:我正在建造一个太阳能发电站,需要帮助计算财务。 - 土地费用为每平方英尺 100 美元 - 我可以以每平方英尺 250 美元的价格购买太阳能电池板 - 我已经谈判好了维护合同,每年需要支付固定的 10 万美元,并额外支付每平方英尺 10 美元; ```作为平方英尺数的函数,首年运营的总费用是多少?``` 学生的解决方案: 设 x 为发电站的大小,单位为平方英尺。 费用: 1. 土地费用:100x 美元 2. 太阳能电池板费用:250x 美元 3. 维护费用:100,000 + 100x = 10 万美元 + 10x 美元 总费用:100x 美元 + 250x 美元 + 10 万美元 + 100x 美元 = 450x + 10 万美元 实际解决方案和步骤: 首先,我们来计算首年运营的总费用。 1. 土地费用:由于土地费用是每平方英尺100美元,所以总共是 100x 美元。 2. 太阳能电池板费用:由于太阳能电池板的价格是每平方英尺250美元,所以总费用是 250x 美元。 3. 维护费用:首先,每年需要支付固定的10万美元,此外,还需要额外支付每平方英尺10美元,所以总维护费用是 10万 + 10x 美元。 将上述三个费用相加,得到首年运营的总费用为: 总费用 = 100x + 250x + (10万 + 10x) = (450x + 11万)美元。 学生计算的总费用:学生计算得到的总费用是450x + 10万美元。 实际计算的总费用:实际计算出的总费用是450x + 11万美元。 学生计算的费用和实际计算的费用不同。学生的总费用中缺少了额外的1万美元维护费用。 学生的解决方案中没有考虑到维护合同中额外的每平方英尺的维护费用,因此与实际解决方案不符。 学生的成绩:不正确。
局限性
开发大模型相关应用时请务必铭记:
虚假知识:模型偶尔会生成一些看似真实实则编造的知识。
虽然模型在训练过程中接触了大量的知识,但它并没有完全记住所见的信息,因此它不甚清楚自己知识的边界。这意味着它可能会尝试回答主题晦涩难懂的问题,并编造听起来合理但实际上并不正确的答案。我们称这些编造的想法为幻觉(Hallucination)。
所谓的【幻觉】就是大模型不准确的地方,目前尚未有框架机制能够判定AI生成的结果和质量,因此对于AI的结果准确性的担忧将一直存在。
目前 OpenAI 等公司正在积极研究解决语言模型的幻觉问题。在技术得以进一步改进之前,开发者可以通过Prompt设计减少幻觉发生的可能。例如,可以先让语言模型直接引用文本中的原句,然后再进行解答。这可以追踪信息来源,降低虚假内容的风险。
如下示例展示了大模型的幻觉。我们要求告诉我们 Apple 公司生产的 iPhone 20 产品的信息,事实上,这个公司是真实存在的,但产品是编造的,而模型一本正经地提供了它编造的知识,而且迷惑性很强。
prompt = f"""
告诉我 Apple 公司生产的 iPhone 20 手机的相关信息
"""
response = get_completion(prompt)
print(response)
很抱歉,我无法为您提供Apple公司生产的iPhone 20手机的相关信息。
建议您通过Apple官网、Apple产品京东自营旗舰店、Apple产品天猫旗舰店等渠道获取更多关于iPhone 20手机的信息。
如果您想了解iPhone 20手机的性能、外观、配置等详细信息,建议您查阅苹果公司的官方资料或者联系苹果公司进行咨询。
由于很容易以假乱真,请读者根据在本系列教程中所学知识,在构建自己的应用程序时尽量避免幻觉情况。幻觉是大模型的一个已知缺陷(注:截至2023年10月),文心一言也在努力解决该问题。
在你希望模型根据文本生成回答时,另一种减少幻觉的策略是先要求模型获取来源于该文本的所有引用信息(任何相关引用,any relevant quotes),然后要求它基于所引用的信息来回答问题,这使得我们能根据答案追溯源文档,通常对减少幻觉非常有帮助。
备注:关于反斜杠使用的说明:
在本教程中,我们使用反斜杠 \ 来使文本适应屏幕大小以提高阅读体验,而没有用换行符 \n 。GPT-3 并不受换行符(newline characters),文心一言并不受换行符(newline characters)的影响,但在你调用其他大模型时,需额外考虑换行符是否会影响模型性能。
RA/SD 衍生者AI训练营。发布者:chris,转载请注明出处:https://www.shxcj.com/archives/72