提示工程是一门新兴的学科,专注于以最佳实践构建LLM的最佳输入,从而尽可能以程序化方式生成目标输出。AI工程师必须知道如何与AI进行交互,以获取可用于应用程序的有利结果。此外,AI工程师还必须知道如何正确提问和编写高质量的提示词。简而言之,让大模型知道我们在说什么,知道我们想干什么,知道我们要得到一个什么结果。那么我们该怎么来写呢?
相较于问大模型1+1这样简单的问题,当我们希望大模型能够处理复杂的提问时,我们需要通过提示词告诉大模型,嘿,你该这样做!
-
三明治结构(适用于一般性提问)
所谓的三明治结构,只是我个人的说法,指的是提示词里面会有三大结构:角色、上下文、任务
下面我用一段prompt来展示(以kimi为例):
从上图可以看到,我在提问的时候,
上下文
其实是最重要的,因为只有上下文写的足够详细,大模型才能弄清楚提问者的想法,从而回答出有价值的回答。当然并不是说其他三部分不够重要,只是相对来说,上下文这一部分需要花的心思最多,比如我除了说我体重有点超标,我还可以提供一些我身体其他的指标,比如最近是否有足够的睡眠,来帮助大模型了解我的身体现状,从而回答出更科学的建议。相较于
上下文
而言,任务
就不用那么复杂了,它一条规则,那就是越明确越具体越好,你应该提供足够的任务信息,并在提示词中使用合适的短语来引导模型给出你所期望的结果。看起来我们好像要提供足够多的信息,才能让大模型知道要干嘛,现实确实是这样的。因为现在的大模型在没有调教的情况下就是个呆瓜。角色
就更好说了,给大模型赋予角色的概念,能让大模型更好贴近场景,控制其输出,在我过往的经验中,在提问的时候,加上角色概念文本,能有效提升大模型回答的准确率。在我们现实使用时,不必拘泥于一定是要这种结构。下面我将根据我学习到的知识和之前撰写prompt的一些经验,写一些小的示例,希望能够做到抛砖引玉。
-
提示原则
-
编写清晰、具体的指令
-
在提示词中应该有层次分明的结构
这里所谓的层次分明的结构,并不是指我们在写提示词的时候,要像json或者yml文件,遵循好格式。而是要告诉大模型,这个和这个是分开的不是一个东西。当然在我们写大规模的提示词时,我们最好也保存层次分明的结构,这样更方便相关人员阅读以及修改,对此我推荐使用markdown格式来编写提示词。
在编写 Prompt 时,我们可以使用各种标点符号作为"分隔符",将不同的文本部分区分开来。分隔符就像是 Prompt 中的墙,将不同的指令、上下文、输入隔开,避免意外的混淆。你可以选择用
```,""",< >,<tag> </tag>,:
等做分隔符,只要能明确起到隔断作用即可。 -
在提示词的末尾,询问模型是否理解问题并指示模型提出更多问题。
如果你正在构建基于聊天机器人的解决方案,那么这样做非常有效。举例来说,你可以在提示词的末尾添加如下文本:
你清楚地理解我的请求了吗?如果没有,请问我关于上下文的问题。这样一来,当我回答时,你就能够更高效地执行我所请求的任务。
-
重复提示
重复提示会取得良好的效果,尤其是当提示词很长时。基本思路是,在提示词中多次添加相同的指令,但每次采用不同的表述方式。
-
添加长度限制
如果你只希望模型回答1个词或者10个句子,那么应该把要求添加到提示词中,这能让大模型回答更简洁,另外一方面长篇大论的回答既消耗大模型token又延长了大模型回答的时间。
-
-
寻求结构化的输出
像一般大模型的回答就是一段话,假如我们在API中去解析这样的字符串是挺难受的,但是我们可以让大模型,根据我们设定的结构来输出,以json格式为例:
-
Bash
我们可以在提示词中写:输出结构按照json格式返回
或者:输出必须被json.loads接受
或者:Make sure the answer is in json format.
在最新的GPT4中,OpenAI在API中推出了结构化输出,确保模型生成的输出将完全匹配开发者提供的Json模式。
-
要求模型检查是否满足条件
如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。大模型根据一定的逻辑去回答问题,如果提问天马行空不着边际,大模型很难做出准确的回答。
-
提供少量样本学习
它指的是LLM仅通过提示词中的几个示例就能进行概括并给出有价值的结果。在使用少样本学习技巧时,你可以给模型提供几个示例,例如下例:
少样本学习技巧提供了具有目标输出的输入示例。然后,在最后一行,我们提供了想让模型完成的提示词。这个提示词与之前的示例具有相同的形式。模型将根据给定示例的模式执行操作。少样本学习是LLM的一个强大的特点,因为它使得LLM高度灵活且适应性强,只需有限的额外信息即可执行各种任务。