easycodesniper

blog by chen qiyi

Prompt

前言

有效地与大型语言模型交流已成为一种关键技能。在openAI 的官方文档中已经给出了最佳实践——如何精心构建问题(prompt engineering),以便从这些大模型中获得最准确、最相关的答案。正确认识并运用这些技巧。

在我的这篇文章中,将总结概括如何编写优秀的 prompt

编写详细的指示 - 大模型不是你肚子里的蛔虫

大模型无法读懂你的想法,它只能根据你给他的信息来返回结果。因此,你需要确保你的 prompt 包含足够的信息,以便大模型理解你的意图。

大模型不会嫌弃你啰嗦,你对问题描述的越详细,你越有可能得到想要的结果。

以下是一些编写 prompt 的策略:

1. 详细描述你的问题,才能得到更相关的回答

为了获得高度相关的回复,请确保请求提供了任何重要的细节或上下文。否则你就把它留给模型去猜你的意思了。

Worse Prompt: 帮我编写一段代码来计算斐波那契数列

得到的回复:

Better Prompt: 写一个 JavaScript 函数来正确高效地计算斐波那契数列,并在关键步骤处给出注释,以解释每个部分的作用以及为什么要这么写

得到的回复:

2. 给大模型一个人设,也给用户一个人设

可以指定大模型在回复时的人设,一个合适且恰当的人设能让大模型更好地响应你的问题。

Worse Prompt: 向我解释一下计算机网络的 OSI 模型

得到的回复:

Better Prompt(给大模型一个人设): 你是一个网络工程师,向我解释一下计算机网络的 OSI 模型

得到的回复:

Better Prompt(给用户一个人设): 我是一个 10 岁的孩子,向我解释一下计算机网络的 OSI 模型

得到的回复:

3. 使用分隔符清楚的指示提问的不同部分

分隔符例如三引号、XML 标记、章节标题等,可以帮助区分文本的不同部分。

Better Prompt:

1
2
3
4
5
6
7
8
9
10
11
12
示例 1: 使用XML标记作为分隔符

你将获得关于同一主题的两篇文章(用XML标记分隔)。首先总结每篇文章的论点。然后指出哪一个论点更站得住脚并解释原因。

<article> insert first article here </article>
<article> insert second article here </article>

示例 2: 使用三引号作为分隔符

总结用三引号分隔的文本

"""insert text here"""

4. 指定完成任务所需的步骤

指定完成任务所需的步骤,大模型会按照步骤执行,而不是直接给出最终答案。这可以确保大模型理解你的意图,并正确地执行任务。

Worse Prompt: 请帮我写一篇关于 xxx 的热点新闻的解读

Better Prompt:

1
2
3
4
请你按照下列步骤来给我撰写一篇关于xxx的热点新闻的解读
Step 1: 检索关于xxx的新闻,选取热度较高的3篇新闻
Step 2: 对3篇新闻进行摘要,并分析其核心观点和原因,先形成解读的目录框架
Step 3: 根据目录框架,对3篇新闻进行详细解读,并解释其观点和原因

5. 向大模型提供例子

Worse Prompt: 我是一个前端初学者,请给我推荐一篇关于 css 的文章

得到的回复:

Better Prompt:

1
2
3
4
5
6
7
我是一个前端初学者,请给我推荐一篇关于css的文章,按照 四等号 中的示例回复我:

====
文章名称:xxx
文章链接:xxx
推荐理由:xxx
====

得到的回复:

6. 指定大模型返回的长度

你可以要求模型生成具有给定目标长度的输出,目标输出长度可以根据单词、句子、段落、项目符号等的数量来指定。

但是请注意,指示模型生成特定数量的单词并不能达到高精度。模型可以更可靠地生成具有特定数量的段落或要点的输出。

Better Prompt:

1
2
3
示例 1: 用三引号分隔的文本在50个单词内进行总结。
示例 2: 用两段话总结用三引号分隔的文本。
示例 3: 用3个要点总结三引号分隔的文本。

向大模型提供参考文本

大模型可以通过自由地发挥来回答你的提问,特别是当被问及深奥的话题或引用和 url 时,这就会导致大模型回复给用户了一个假答案

为大模型提供参考文本可以限制它的过度自由发挥,同时也减少得到假答案的可能性

如果我们可以为模型提供与当前查询相关的可信信息,那么我们可以指示模型使用提供的信息来组成它的答案。

Better Prompt:

1
2
3
4
5
使用三引号分隔的文章回答问题。如果在文章中找不到答案,就写“我找不到答案”。

"""insert article here"""

问题:xxx

考虑到所有模型都有有限的上下文窗口,我们需要一些方法来动态查找与所问问题相关的信息 — 这就是需要用到 知识库

将复杂的任务拆分为更简单的子任务

正如将复杂系统分解为一组模块化组件是软件工程中的良好实践一样,提交给语言模型的任务也是如此。复杂任务往往比简单任务的错误率更高。

此外,复杂的任务通常可以重新定义为简单任务的工作流,其中早期任务的输出用于构造后续任务的输入。

对于需要大量独立指令来处理不同情况的任务,首先对查询类型进行分类,并使用该分类来确定需要执行哪些指令。还可以递归地应用此过程,将任务分解为一系列阶段。这可以通过定义固定类别和硬编码与处理给定类别中的任务相关的指令来实现。

Better Prompt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

// 先对用户查询进行分类,类似于定义不同的功能分支

您将获得客户服务查询。将每个查询划分为主要类别和次要类别。根据主要类别和次要类别给出你的回复。
主要类别:前端 和 后端
次要类别:
前端次要类别:ui设计 和 接口调用
后端次要类别:bug修复 和 接口开发

// 根据分类,给出对应的回复

当用户询问你的上下文涉及「ui设计」时,请按照以下步骤为用户提供帮助:
- Step 1:询问用户 ui 的类型,例如:按钮、输入框、弹窗等
- Step 2: 询问用户要设计的 ui 的大致样式,例如尺寸、颜色、字体等
- Step 3: 根据用户要求给出ui设计的html 和 css代码,并询问用户是否对此满意
- Step 4: 如果用户满意,则 接着询问用户该ui是否需要设计JS逻辑;否则,重复步骤 1 和 2
- Step 5: 如果用户需要设计JS逻辑,则根据用户需求给出JS代码;如果用户不需要设计JS逻辑,则结束

当用户询问你的上下文涉及「接口调用」时,请按照以下步骤为用户提供帮助:
- Step 1: 询问用户接口类型、接口url 和 接口参数
- Step 2: 询问用户是否指定某个工具库进行网络请求,如果用户未指定,则默认使用axios来编写请求
- Step 3: 根据用户需求给出请求代码,并询问用户是否对此满意
- Step 4: 如果用户满意,则 结束;否则,重复步骤 1 和 2

当用户询问你的上下文涉及「bug修复」时,请按照以下步骤为用户提供帮助:
- Step 1: 询问用户bug的位置、bug描述和bug截图
- Step 2: 根据用户需求给出修复代码,并询问用户是否对此满意
- Step 3: 如果用户满意,则 结束;否则,重复步骤 1 和 2

当用户询问你的上下文涉及「接口开发」时,请按照以下步骤为用户提供帮助:
- Step 1: 询问用户接口类型、接口url 和 接口参数
- Step 2: 询问用户使用什么编程语言或者框架来编写接口代码,如果用户未指定,则默认使用Java
- Step 3: 根据用户需求给出接口代码,并询问用户是否对此满意
- Step 4: 如果用户满意,则 结束;否则,重复步骤 1 和 2

如果你已经理解上述内容,请回复我「已理解」,我会在下一条问题中咨询你问题,请根据上述内容进行匹配和回答。

使用这种方法的好处就在于:

通过发出特殊字符串来指示模型,以指示对话状态何时发生变化。这使我们能够将系统转换为状态机,其中状态决定注入哪些指令。通过跟踪状态,与该状态相关的指令,以及可选的允许从该状态转换的状态。

得到的回复:

给模型时间去「思考」

当试图立即回答问题时,模型会犯更多的推理错误,而不是花时间找出答案。在回答问题之前询问“思维链”可以帮助模型更可靠地推理出正确的答案。

1. 在匆忙得出结论之前,指示模型自己找出解决方案

当我们明确地指示模型在得出结论之前从第一原则进行推理时,我们会得到更好的结果。例如,假设我们需要一个模型来评估学生对数学问题的解决方案。最明显的解决方法就是简单地询问模型学生的解决方案是否正确。

来看下面的例子:

Worse Prompt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
用户:

判断学生的答案是否正确。

问题陈述:我正在建造一个太阳能装置,我需要帮助来解决财务问题。
-土地成本为每平方英尺100美元
-我能以每平方英尺250美元的价格买到太阳能电池板
-我谈了一份维护合同,每年要花我10万美元,每平方英尺还要额外花10美元
第一年运营的总成本是多少作为平方英尺数的函数?

学生解答:设x为装置面积,单位为平方英尺。
1. 土地成本:100倍
2. 太阳能电池板成本:250倍
3. 维护费用:10万+ 100倍
总成本:100x + 250x + 100000 + 100x = 450x + 100000


大模型回复: 解决方案正确!

但是这个学生的答案其实是不正确的!

在我们可以通过提示模型首先生成自己的解决方案来让模型成功地注意到这一点,即让模型先自己进行思考。

Better Prompt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
用户:

首先想出你自己解决这个问题的办法。然后将你的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。在你自己做了这道题之前,不要判断这个学生的答案是否正确。

问题陈述:我正在建造一个太阳能装置,我需要帮助来解决财务问题。
-土地成本为每平方英尺100美元
-我能以每平方英尺250美元的价格买到太阳能电池板
-我谈了一份维护合同,每年要花我10万美元,每平方英尺还要额外花10美元
第一年运营的总成本是多少作为平方英尺数的函数?

学生解答:设x为装置面积,单位为平方英尺。
1. 土地成本:100倍
2. 太阳能电池板成本:250倍
3. 维护费用:10万+ 100倍
总成本:100x + 250x + 100000 + 100x = 450x + 100000


大模型回复:

设x为装置面积,单位为平方英尺。
1. 土地成本:100倍
2. 太阳能电池板成本:250倍
3. 维护费用:10万+ 10倍
总成本:100x + 250x + 100000 + 10x = 360x + 100000

这个学生的答案不正确。他们在维修成本计算中犯了一个错误,用100倍代替10倍。第一年运营的正确总成本是360x + 100,000。

2. 使用内心独白或查询序列来隐藏模型的推理过程

前面的策略表明,在回答特定问题之前,模型有时对问题进行详细的推理是很重要的。

对于某些应用程序,模型用于得出最终答案的推理过程可能不适合与用户共享。例如,在辅导应用程序中,我们可能希望鼓励学生自己找出答案,但模型对学生解决方案的推理过程可能会向学生揭示答案。

内心独白是一种可以用来缓解这种情况的策略。内心独白的思想是指示模型将对用户隐藏的部分输出放入结构化格式中,以便于解析它们。然后,在将输出呈现给用户之前,对输出进行解析,只显示想要给用户看到的部分。

Better Prompt

1
2
3
4
5
6
7
8
9
10
11
12
13
你作为一个专业和资深数学老师,判断学生的答案是否正确。

按照以下步骤回答用户查询,先不要输出任何三引号(""")中的内容,等执行完所有步骤时再根据步骤的要求输出应该输出的内容。

Step 1: 首先找出你自己解决问题的方法。不要依赖学生的答案,因为它可能是错误的。将此步骤的所有工作用三引号(""")括起来。

Step 2: 将你的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。将此步骤的所有工作用三引号(""")括起来。

Step 3: 如果学生犯了一个错误,确定你可以给学生什么提示而不泄露答案。将此步骤的所有工作用三引号(""")括起来。

Step 4: 如果学生犯了错误,只给学生提供上一步的提示,不要输出三引号中的内容。不要写“Step 4: .....”,而要写“提示: ...”。

如果你已经理解上述内容,请回复我「已理解」,我会在下一条问题中给出数学问题 和 学生的解决方案,请根据上述内容进行匹配和回答。

测试 Prompt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
用户:

问题陈述:我正在建造一个太阳能装置,我需要帮助来解决财务问题。
-土地成本为每平方英尺100美元
-我能以每平方英尺250美元的价格买到太阳能电池板
-我谈了一份维护合同,每年要花我10万美元,每平方英尺还要额外花10美元
第一年运营的总成本是多少作为平方英尺数的函数?

学生解答:设x为装置面积,单位为平方英尺。
1. 土地成本:100倍
2. 太阳能电池板成本:250倍
3. 维护费用:10万+ 100倍
总成本:100x + 250x + 100000 + 100x = 450x + 100000


大模型:

提示: 请检查维护合同中变量成本的计算,确保每平方英尺的额外费用被正确计算。