面向Java开发者的ChatGPT提示词工程(4)

2023-09-01 16:48:33 浏览数 (1)

在之前的文章中,我们了解到了编写明确具体的指令关键原则的四种策略,它们分别是:

  • 使用分隔符清楚地指示输入的不同部分。
  • 要求GTP结构化输出。
  • 要求GTP检查是否满足条件。
  • 写示例时提示词要尽量少一些。

接下来,我们将继续了解第二个关键原则:给 GPT 一定的“思考”时间

给 GPT 一定的“思考”时间

当 GPT 匆忙给出错误结论时,我们可以考虑重新构思问题,并要求 GPT 在给出最终答案之前提供一系列相关的推理过程。就像人类一样,如果我们给予 GPT 一个过于复杂的任务,要求它在短时间内或者用较少的词语来完成,那么它很可能会随意猜测,进而导致错误答案的产生。实际上,人也会在类似情况下犯错误。举个例子,如果我们让一个人在没有足够时间来计算复杂数学问题的情况下,要求其给出答案,那么他们很可能也会出错。

明确任务完成所需的步骤

第一个策略是明确任务完成所需的步骤。我们用以下的例子阐释:

代码语言:javascript复制
 public static void main(String[] args) {
     String text = "我说道:“爸爸,你走吧。”n"
               "他望车外看了看,说:“我买几个橘子去。你就在此地,不要走动。”n"
               "我看那边月台的栅栏外有几个卖东西的等着顾客。走到那边月台,须穿过铁道,须跳下去又爬上去。父亲是一个胖子,走过去自然要费事些。我本来要去的,他不肯,只好让他去。n"
               "我看见他戴着黑布小帽,穿着黑布大马褂,深青布棉袍,蹒跚地走到铁道边,慢慢探身下去,尚不大难。可是他穿过铁道,要爬上那边月台,就不容易了。"
               "他用两手攀着上面,两脚再向上缩;他肥胖的身子向左微倾,显出努力的样子。这时我看见他的背影,我的泪很快地流下来了。我赶紧拭干了泪。怕他看见,也怕别人看见。n"
               "我再向外看时,他已抱了朱红的橘子往回走了。过铁道时,他先将橘子散放在地上,自己慢慢爬下,再抱起橘子走。到这边时,我赶紧去搀他。"
               "他和我走到车上,将橘子一股脑儿放在我的皮大衣上。于是扑扑衣上的泥土,心里很轻松似的。过一会儿说:“我走了,到那边来信!”我望着他走出去。"
               "他走了几步,回过头看见我,说:“进去吧,里边没人。”等他的背影混入来来往往的人里,再找不着了,我便进来坐下,我的眼泪又来了。n";

     String prompt = "按照如下步骤完成:n"
               "第一步,将三个反引号之间的文本总结为一句话的概要。n"
               "第二步,把概要翻译成英语。n"
               "第三步,列出英语概要中出现的人物。n"
               "第四步,以JSON格式输出,包括以下字段:english_summary、persons_num。n"
               "每个步骤按行输出。n"
               "```%s```";
     String response = getCompletion(String.format(prompt, text));
     System.out.println(response);
 }

我们会给出一段父亲给儿子买橘子的故事段落,然后让 GPT 完成一系列任务,包括总结这段文字、翻译成英语、列出英语总结中的每个人物,并输出一个包含英语总结和人物数量的JSON对象。输出结果如下:

代码语言:javascript复制
概要:一个人送父亲去买橘子,父亲穿过铁道回来时费力,他看到父亲的背影很感动,父亲走后他哭了。
English summary: A person sends his father to buy oranges. When the father returns, he struggles to climb back over the railway. The person is moved by his father's efforts and cries when he leaves.
Persons: the person, the father
JSON输出:
{
    "english_summary": "A person sends his father to buy oranges. When the father returns, he struggles to climb back over the railway. The person is moved by his father's efforts and cries when he leaves.",
    "persons_num": 2
}

有趣的是,英文概要和人物的说明都是英文的,这可能不是我想要的。我们用另一个提示词来完成同样的任务。在这个提示词中,我使用了一种我很喜欢使用的格式,来指定 GPT 的输出结构:

代码语言:javascript复制
 public static void main(String[] args) {
     String text = "我说道:“爸爸,你走吧。”n"
               "他望车外看了看,说:“我买几个橘子去。你就在此地,不要走动。”n"
               "我看那边月台的栅栏外有几个卖东西的等着顾客。走到那边月台,须穿过铁道,须跳下去又爬上去。父亲是一个胖子,走过去自然要费事些。我本来要去的,他不肯,只好让他去。n"
               "我看见他戴着黑布小帽,穿着黑布大马褂,深青布棉袍,蹒跚地走到铁道边,慢慢探身下去,尚不大难。可是他穿过铁道,要爬上那边月台,就不容易了。"
               "他用两手攀着上面,两脚再向上缩;他肥胖的身子向左微倾,显出努力的样子。这时我看见他的背影,我的泪很快地流下来了。我赶紧拭干了泪。怕他看见,也怕别人看见。n"
               "我再向外看时,他已抱了朱红的橘子往回走了。过铁道时,他先将橘子散放在地上,自己慢慢爬下,再抱起橘子走。到这边时,我赶紧去搀他。"
               "他和我走到车上,将橘子一股脑儿放在我的皮大衣上。于是扑扑衣上的泥土,心里很轻松似的。过一会儿说:“我走了,到那边来信!”我望着他走出去。"
               "他走了几步,回过头看见我,说:“进去吧,里边没人。”等他的背影混入来来往往的人里,再找不着了,我便进来坐下,我的眼泪又来了。n";

     String prompt = "按照如下步骤完成:n"
               "第一步,将三个反引号之间的文本总结为一句话的概要。n"
               "第二步,把概要翻译成英语。n"
               "第三步,列出英语概要中出现的人物。n"
               "第四步,以JSON格式输出,包括以下字段:english_summary、persons_num。n"
               "用以下格式回答:n"
               "中文概要:<总结的概要>n"
               "英文概要:<英语概要>n"
               "人物:<英语概要中出现的人物>n"
               "JSON:<english_summary、persons_num的JSON格式输出>n"
               "```%s```";
     String response = getCompletion(String.format(prompt, text));
     System.out.println(response);
 }

在这个提示词中,我们在询问了类似的东西,提示词的开头是一样的。然后我们要求 GPT 使用中文概要、英文概要、人物和JSON的格式。我们运行以后的输出:

代码语言:javascript复制
中文概要:父亲买橘子,儿子送行,父亲过铁道时艰难,儿子看着流泪。
英文概要:Father went to buy oranges, son saw him off. Father had difficulty crossing the railway, son cried. 
人物:Father, son
JSON:{"english_summary": "Father went to buy oranges, son saw him off. Father had difficulty crossing the railway, son cried.", "persons_num": 2}

正如你所看到的,GPT 使用了我们要求的格式。我们已经给它了文本,然后它给我们了中文概要、英文概要、人物和JSON。

在匆忙得出结论之前,指示 GPT 自己找出解决方案

我们下一个策略是:在匆忙得出结论之前,指示 GPT 自己找出解决方案。有时候当我们明确指示 GPT 在得出结论之前先理出自己的解决方案时,我们会得到更好的结果。这个策略跟我们之前讨论的一样,就是给 GPT 一些时间去解决问题,而不是直接说答案对不对,就像人一样。

在下面的例子中,我们要求 GPT 判断学生的解答是否正确。

代码语言:javascript复制
 public static void main(String[] args) {
     String prompt = "判断学生的解答是否正确。n"
               "问题:n"
               "《红岩》一共有288页,小明每天读36页书,几天可以读完《红岩》?nn"
               "学生解答:n"
               "288 / 36 = 10(天)n"
               "小明10天可以读完《红岩》。";
     String response = getCompletion(prompt);
     System.out.println(response);
 }

这是一个数学应用题,然后是学生的解答。学生的解答实际上是错误的,因为288 / 36等于 8,不是10。让我们运行一下看看:

代码语言:javascript复制
学生的解答是正确的。

如果你只是读一下学生的解答,你会发现这个解答看起来是正确的。因此,GPT 只是像我一样粗略地阅读了一下,就同意了学生的解答。

我们优化一下提示词,可以让 GPT 先解答这个问题,然后再比较自己的解答和学生的解答:

代码语言:javascript复制
public static void main(String[] args) {
    String prompt = "判断学生的解答是否正确。n"
              "按照如下步骤完成:n"
              "第一步,你对这个问题进行解答。n"
              "第二步,将你的解答与学生的解答进行比较,并评估学生的解答是否正确。n"
              "在你自己解答问题之前,不要确定学生的解答是否正确。n"
              "用以下的格式回答:n"
              "正确解答:<你的解题步骤和解答>n"
              "学生的答案和你的答案的比较:<一样或者不一样>n"
              "学生答案的判断结果:<正确或者错误>n"
              "问题:n"
              "《红岩》一共有288页,小明每天读36页书,几天可以读完《红岩》?nn"
              "学生解答:n"
              "288 / 36 = 10(天)n"
              "小明10天可以读完《红岩》。";
    String response = getCompletion(prompt);
    System.out.println(response);
}

我们在这个提示中告诉模型什么?它的任务是确定学生的解答是否正确。为了完成任务做以下步骤:首先,解决自己的问题。然后比较你的解答和学生的解答,评估学生的解答是否正确。在你自己解决问题之前,不要决定学生的解答是否正确。一定要非常清楚,确保你自己解决了这个问题。因此,我们使用了相同的技巧来优化了提示词。

运行结果如下:

代码语言:javascript复制
正确解答:288÷36=8(天)
学生的答案和你的答案的比较:不一样
学生答案的判断结果:错误

总结

我们了解第二个关键原则:给 GPT 一定的“思考”时间。当 GPT 匆忙给出错误结论时,我们可以考虑重新构思问题,并要求 GPT 在给出最终答案之前提供一系列相关的推理过程。主要有以下两个策略:

  • 明确任务完成所需的步骤。
  • 在匆忙得出结论之前,指示 GPT 自己找出解决方案。

0 人点赞