Prompt进阶2:LangGPT(构建高性能Prompt策略和技巧)–最佳实践指南
0.前言
左图右图 prompt 基本是一样的,差别只在提示工程这个词是否用中英文表达。我们看到,一词之差,回答质量天壤之别。为了获得理想的模型结果,我们需要调整设计提示词,这也就是所谓的提示工程。
一个广泛的理解误区就是将 prompt 简单理解为自己精心设计的那一小段提示词,而忽略了prompt 的其他来源 。
我们用输入法做个类比,第一张图片中的 “春眠” 是我们的输入,“不觉晓” 是模型输出,所以 “春眠” 是 Prompt。到了第二张图片, “春眠不觉晓” 是模型输入(“不觉晓”是模型前一轮的输出),“处处闻啼鸟” 是模型输出,所以 “春眠不觉晓” 是 Prompt。prompt 的来源可以是我们的预设 prompt,也可以是用户的输入,甚至模型自己之前的输出也是 prompt。所以,要用好大模型能力,我们应意识到:“所有会被模型用于预测输出结果的内容,都是 Prompt”。
相比一般提示词,将提示词这一作文题变为填空题,编写门槛降低的同时,更加清晰和强大。
1.1 六大提高性能的策略
1.1 策略一:清晰地表达指令
GPT 无法读取您的思维。如果输出过长,要求它提供简短的回复。如果输出过于简单,要求它提供专业级的写作。如果您不喜欢输出的格式,请示范您希望看到的格式。GPT 模型需要猜测的东西越少,您得到想要的结果的可能性就越大。
技巧:
- 在查询中包含更多细节以获取更相关的回答
- 要求模型采用特定的角色
- 使用分隔符清楚地指示输入的不同部分
- 指定完成任务所需的步骤
- 提供示例
- 指定期望的输出长度
1.2 策略二:提供参考文本
GPT 模型可以自信地编造虚假的答案,尤其是在被问到深奥的话题或被要求提供引用和 URL 时。就像考试前准备的笔记本可以帮助学生取得更好的成绩一样,为 GPT 模型提供参考文本也可以减少它编造答案的可能性。
技巧:
- 指示模型使用提供的参考文本进行回答
- 指示模型使用参考文本中的引文进行回答
1.3 策略三:将复杂任务分解为更简单的子任务
正如在软件工程中将复杂系统分解为一组模块组件是一个好的实践一样,提交给 GPT 模型的任务也应该进行拆分。复杂的任务错误率往往比简单任务高。此外,复杂任务通常可以重新定义为一系列更简单任务的工作流,其中早期任务的输出被用于构造后期任务的输入。
技巧:
- 使用意图分类识别与用户查询最相关的指令
- 对需要非常长对话的对话应用,汇总或过滤之前的对话
- 分段摘要长文档,递归构建完整摘要
1.4 策略四:给予 GPT“思考”的时间
如果要求您立刻计算 17 乘以 28,您可能不会立即知道答案,但仍能通过思考得出正确解。类似地,GPT 模型如果被要求立即回答也更容易出现推理错误,而逐步思考问题可以更可靠地得出正确答案。
技巧:
- 指示模型在匆忙得出结论之前自己推导出解决方案
- 使用内心独白或一系列查询来隐藏模型的推理过程
- 询问模型是否在之前的轮次中遗漏了任何信息
1.5 策略五:使用外部工具
补充 GPT 模型的输入短板,为其提供其他工具的输出。例如,文本检索系统可以告知 GPT 模型相关文档的信息。如果一项任务可以由工具而不是 GPT 模型更可靠、更高效地完成,则将其外包可以取得两全其美的效果。
技巧:
- 使用基于嵌入的搜索实现高效的知识检索
- 使用代码执行进行更准确的计算或调用外部 API
- 允许模型访问特定函数
1.6 策略六:系统地测试更改
有时候很难分辨出某项更改(如新指令或设计)是否提升了系统性能。查看几个例子可能会提示哪种方法更好,但样本量太小时,难以区分真正的改进与随机幸运。也许某项更改对某些输入有益,但对其他输入有害。
评估程序(或“测评”)对优化系统设计很有用。好的测评应该具有以下特点:
- 代表真实使用情况(或至少包含多样性)
- 包含大量测试用例以增强统计功效(参见下表)
- 易于自动化或重复
需检测的差异 | 需样本量(95%置信度) |
---|---|
30% | ~10 |
10% | ~100 |
3% | ~1000 |
1% | ~10000 |
模型输出的评估可以由计算机、人类或两者的组合来完成。计算机可以用客观标准(如只有单一正确答案的问题)自动进行测评,也可以用其他模型查询对一些主观或模糊标准进行测评。OpenAI Evals是一个开源软件框架,提供了创建自动化测评的工具。
对于输出范围广泛且同等高质量的问题(如需要长答案的问题),基于模型的测评可发挥作用。模型测评与需要人工评估的问题界限模糊,随着模型变得越来越强大而不断扩展。我们鼓励您进行试验,了解基于模型的测评对您的用例能发挥多大作用。
技巧:
- 根据参考标准答案评估模型输出
2.技巧深入
上述每种策略都可以用具体的技巧来实现。这些技巧旨在提供思路,绝非面面俱到,您应随意尝试这里未涉及的创造性思路。
2.1 策略一:清晰地表达指令
技巧:在查询中包含更多细节以获取更相关的回答
为了获得高度相关的回复,查询需要提供任何重要的细节或上下文信息,否则就要由模型猜测您的意图。
劣质 | 优质 |
---|---|
Excel 中如何相加数字? | 在 Excel 中如何对一行金额自动相加?我想对整个工作表的行进行求和,总和显示在右边一列"总计"中。 |
谁是总统? | 2021年墨西哥总统是谁,选举频率是多久一次? |
编写代码计算斐波那契数列。 | 用 TypeScript 编写一个函数来有效地计算斐波那契数列。对代码添加详细注释以解释每个部分的作用及编写方式。 |
摘要会议记录。 | 用一段话摘要会议记录。然后用 markdown 列表罗列发言人及每个人的要点。最后,列出会议记录中发言者提出的后续步骤或行动事项(若有)。 |
技巧:要求模型采用特定的角色
系统消息可用于指定模型在回复时采用的角色。
技巧:使用分隔符清楚地指示输入的不同部分
三引号、XML标签、标题等分隔符可以帮助标记需不同对待的文本片段。
对于简单的任务,使用分隔符可能不会影响输出质量。然而,任务越复杂,明确任务细节就越重要。不要让 GPT 模型费劲理解您到底在要求什么。
技巧:指定完成任务所需的步骤
有些任务最好用一系列步骤来表达。明确写出步骤可以让模型更容易遵循。
技巧:提供示例
在所有示例上演示任务的各种变化通常比仅给出说明更高效,但在某些情况下提供示例可能更简单。例如,如果您希望模型模仿回复用户查询的特定风格,而这种风格难以明确表达。这被称为 “few-shot” 提示。
技巧:指定期望的输出长度
您可以要求模型生成特定目标长度的输出。目标输出长度可以以单词数、句子数、段落数、项目符号数等来指定。但是,指示模型生成特定数量的单词不能高精度实现。模型可以更可靠地生成特定段落数或项目符号数的输出。
2.2 策略二:提供参考文本
技巧:指示模型使用提供的参考文本进行回答
如果我们能为模型提供与当前查询相关的可信信息,那么我们可以指示模型使用提供的信息来组成其回答。
鉴于 GPT 模型具有有限的上下文窗口,为了应用此技巧,我们需要某种方法根据问题动态查找相关信息并添加到模型输入中。嵌入可用于实现高效的知识检索。请参阅技巧“使用基于嵌入的搜索实现高效知识检索”以获取更多详细信息。
技巧:指示模型使用参考文本中的引文进行回答
如果输入补充了相关知识,则可以轻松要求模型在答案中添加引文,引用提供文档的相关段落。输出中的引文然后可以通过与提供文档的字符串匹配来程序化验证。
2.3 策略三:将复杂任务分解为更简单的子任务
技巧:使用意图分类识别与用户查询最相关的指令
对于需要大量独立指令集来处理不同情况的任务,首先对查询进行分类以确定所需指令会很有益。这可以通过定义固定类别并针对每个类别硬编码相关指令来实现。该过程也可以递归应用以将任务分解成一系列阶段。这种方法的优点是每个查询只包含执行任务下一阶段所需的指令,这可以与使用单个查询执行整个任务相比降低错误率。这也可以降低成本,因为更大的提示需要更高的运行成本(查看价格信息)。
例如,对于客户服务应用,查询可以划分为以下类别:
根据客户查询的分类,可以为 GPT 模型提供更具体的指令来处理后续步骤。例如,假设客户需要“故障排除”的帮助。
注意,模型被指示在对话状态发生变化时输出特殊字符串。这使我们可以将系统转化为状态机,其中状态确定注入哪些指令。通过跟踪状态、该状态下相关的指令,以及从该状态允许的状态转移,我们可以为用户体验设置更难以用不太结构化的方法实现的约束。
技巧:对需要非常长对话的对话应用,汇总或过滤之前的对话
由于 GPT 模型具有固定的上下文长度,因此将整个对话包含在上下文窗口内的用户与助手之间的对话无法无限期地继续。
这一问题有多种解决方法,一种是在输入大小达到预定阈值长度时,使用一个查询来总结对话的一部分,并将之前对话的摘要包含在系统消息中。或者,可以在整个对话的过程中异步地在后台总结之前的对话。
另一种解决方案是动态选择与当前查询最相关的之前对话部分。请参阅技巧“使用基于嵌入的搜索实现高效知识检索”。
技巧:分段摘要长文档,递归构建完整摘要
由于 GPT 模型具有固定的上下文长度,它们无法在单个查询中概括比上下文长度减去生成摘要长度还要长的文本。
要摘要像书籍这样的非常长文档,我们可以使用一系列查询逐部分摘要文档。部分摘要可以连接在一起生成摘要的摘要。该过程可以递归进行,直到整个文档被摘要。如果为了理解后面部分需要使用前面部分的信息,则可以在摘要某点内容时,将该点之前文本的运行摘要也包括在内,这一技巧也很有用。OpenAI 之前的研究已经研究了使用 GPT-3 变体递归摘要书籍的效果。
2.4 策略四:给予 GPT“思考”的时间
技巧:指示模型在匆忙得出结论之前自己推导出解决方案
有时候明确地让模型先自行推理出答案再回复用户,可以获得更好的效果。
例如,我们想让模型评判一个学生对数学问题的解答。 最直接的方法是简单地询问模型该解答是否正确。
但如果我们首先让模型自己解出题目并生成答案,再让其比较学生的答案,就更容易发现问题:
SYSTEM: 首先自己解出这道题并生成答案。然后再比较你的答案和学生的答案,判断学生的答案是否正确。在比较之前,不要依赖学生的答案来决定其是否正确。
USER: <插入题目>
<插入学生答案>
ASSISTANT: <模型先生成自己的答案>
<模型比较两个答案并作出评价>
技巧:使用内心独白或一系列查询来隐藏模型的推理过程
有时候我们不想让用户看到模型的全部推理过程,只需要展示最后的回复。
这时可以使用"内心独白"把需要隐藏的部分放入特定格式中,在展示给用户前把这些部分删除。
或者,可以进行一系列查询,其中只有最后一个查询的输出会展示给用户。
#隐藏查询1: 仅提供问题描述,让模型解出答案
#隐藏查询2: 提供问题描述、模型解答和学生解答,让模型判断学生解答的正确性
#可见查询: 假设模型是一个有帮助的导师,如果学生错误,给出提示;如果正确,给予鼓励
技巧:在前几轮后询问模型是否遗漏了相关信息
当我们要求模型列举某文本中的所有相关摘录时,模型常会过早停止而未罗列全部。
这时可以在前几轮查询后,再询问模型是否还遗漏了相关内容,以获取更完整的结果。
2.5 策略:使用外部工具
技巧:使用基于嵌入的搜索实现高效的知识检索
我们可以在模型的输入中加入相关的外部信息,帮助其生成更准确的回复。
例如,如果用户询问一个具体的电影,将该电影的高质量信息(演员、导演等)也加入输入中会很有用。
通过使用文本嵌入可以实现高效的知识检索,从而动态地在运行时将相关信息加入模型输入中。
具体实现可以参考 OpenAI Cookbook。
技巧:使用代码执行进行更精确的计算或调用外部 API
GPT 模型自己进行算术运算或长时间计算时误差很大。这时可以让其编写代码进行运算并运行。
代码执行也可以用来调用外部 API。如果事先教会模型如何使用某 API,它可以编写调用该 API 的代码。
需要注意,运行模型生成的代码有安全风险,需要采取防护措施。
技巧:系统地测试各种改变
有时候很难判断某项改变是否提升了系统性能。仅观察几个例子来判断是不可靠的。
适当的评估流程对优化系统设计非常有用。好的评估应该具有代表性、包含足够多的测试用例。
评估可以由计算机、人工或两者混合来进行。计算机可以自动进行客观的评估。OpenAI Evals 提供了用于构建自动评估的开源工具。
当存在多种可被认为同等优质的输出时,使用模型进行评估也可行。我们鼓励针对不同使用案例进行试验,衡量模型评估的可行性。
技巧:参照标准答案来评估模型输出
如果问题的正确答案需要包含某些已知的事实,我们可以用模型查询来统计答案中包含了多少需要的事实。
例如:
SYSTEM: 检查提交的答案是否直接包含下列信息:
- Neil Armstrong 是第一个登月的人
- Neil Armstrong 首次登月的日期是 1969年7月21日
对于每个要点:
1 - 重述要点
2 - 提供与要点最相关的答案摘录
3 - 分析仅看摘录的人是否可以推断出该要点,解释你的推理过程
4 - 如果答案是肯定的,写 "yes",否则写 "no"
最后,统计"yes"的个数,用以下格式提供:
{"count": <yes的个数>}
如果答案满足所有要点,count 将为要点的总数。如果仅满足部分要点,count 将小于要点总数。
这样可以构建不同的模型评估变体来统计答案与标准答案的重合情况,以及是否存在矛盾。
更多优质内容请关注公号:汀丶人工智能;会提供一些相关的资源和优质文章,免费获取阅读。
- 参考链接:
https://github.com/EmbraceAGI/LangGPT/tree/main
https://github.com/EmbraceAGI/LangGPT/blob/main/Docs/GPTBestPractise.md