提示工程课后小结及思考 | 豆包MarsCode AI刷题

134 阅读13分钟

前言

这两天学习了模型I/O和提示工程,认识到了调用大模型时的提示是非常重要的,于是写一篇笔记总结一下课程中提到的一些常用的提示工程方法,并完成课后的思考题。

提示工程

吴恩达老师说提示工程有两条原则:第一条原则是写出清晰而具体的指示,第二条原则是给模型思考的时间。所以提示工程的重中之重就是怎么给出清晰而具体的指示,并将这个指示结构化、模板化,以待以后的复用。

提示框架包括:指令、上下文、提示输入和输出指示器。

LangChain 提示模板的类型

  • PromptTemplate: 最常用的String提示模板,之前的课程中已经使用过该模板。
  • ChatPromptTemplate: 常用的Chat提示模板,组合各种角色的消息模板,传入聊天模型。
  • FewShotPromptTemplate: 少样本提示模板,通过提供少量的示例来提示模型该如何回答。
  • PipelinePrompt: 把几个提示组合起来使用

这几个模板的使用方法在课程文档里面都有,这里就不再赘述了,下面我们来看一下思考题。

问题一:尝试使用PromptTemplate中的jinja2等参数

jinja2提供了一些 f-string 不具备的高级特性,如条件判断、循环、过滤器等,从而可以创建动态性更强的模板。

下面这个代码就是根据用户兴趣,给出在某个地点的旅游建议。

from langchain import PromptTemplate
from langchain_openai import ChatOpenAI
import os

# 定义 Jinja2 模板
template = """
{% if interests|length > 1 %}
    您有多个兴趣!请基于兴趣给出旅行推荐:
    {% for interest in interests %}
        - 对 {{ destination }} 的 {{ interest }} 主题推荐:{{ recommendations[interest] }}
    {% endfor %}
{% else %}
    针对您在 {{ destination }} 的兴趣 {{ interests[0] }},我们推荐:{{ recommendations[interests[0]] }}
{% endif %}
"""

prompt = PromptTemplate(
    input_variables=["destination", "interests", "recommendations"],
    template=template,
    template_format="jinja2",
    validate_template=True
)

input_data = {
    "destination": "巴黎",
    "interests": ["美食", "历史"],
    "recommendations": {
        "美食": "尝试巴黎的法式大餐和街头美食",
        "历史": "参观卢浮宫和凡尔赛宫,探索法国的历史文化"
    }
}

output = prompt.format(**input_data)
print(output)

llm = ChatOpenAI(model=os.environ["LLM_MODELEND"])
output = llm(prompt.format(**input_data))
print(output.content)

运行结果如下:

    用户对旅行有多个兴趣!请基于兴趣给出旅行推荐:
    
        - 对 巴黎 的 美食 主题推荐:尝试巴黎的法式大餐和街头美食
    
        - 对 巴黎 的 历史 主题推荐:参观卢浮宫和凡尔赛宫,探索法国的历史文化

好的,以下是根据用户兴趣给出的旅行推荐:

1. **对巴黎的美食主题推荐**:
    - **尝试巴黎的法式大餐**:巴黎是法国美食的代表城市之一,有许多著名的法式餐厅。你可以品尝到正宗的法式鹅肝、焗蜗牛、法式甜点等。
    - **探索巴黎的街头美食**:巴黎的街头美食也非常有特色,比如可丽饼、法式热狗、奶酪等。你可以在街头巷尾找到这些美食,感受巴黎的市井气息。
    - **参加美食之旅**:如果你想更深入地了解巴黎的美食文化,可以参加美食之旅。这些旅行通常会带你参观当地的市场、餐厅和食品加工厂,让你品尝到各种不同的美食。
    - **品尝当地的葡萄酒**:法国是世界著名的葡萄酒产区之一,巴黎也有许多葡萄酒酒吧和餐厅。你可以品尝到当地的葡萄酒,了解法国的葡萄酒文化。

2. **对巴黎的历史主题推荐**:
    - **参观卢浮宫**:卢浮宫是世界上最大的艺术博物馆之一,收藏了无数珍贵的艺术品和文物。你可以在这里欣赏到蒙娜丽莎、维纳斯等著名的艺术品,了解法国的艺术历史。
    - **探索凡尔赛宫**:凡尔赛宫是法国历史上最重要的宫殿之一,也是世界上最大的宫殿之一。你可以在这里参观宫殿的建筑和装饰,了解法国的宫廷文化。
    - **游览巴黎的历史街区**:巴黎有许多历史悠久的街区,比如巴黎圣母院所在的西岱岛、圣日耳曼区等。你可以在这里漫步,欣赏到古老的建筑和街道,感受巴黎的历史氛围。
    - **参观博物馆和纪念馆**:巴黎有许多博物馆和纪念馆,比如法国国家历史博物馆、巴黎市立博物馆等。你可以在这里了解法国的历史和文化,感受巴黎的文化底蕴。
    - **参加历史之旅**:如果你想更深入地了解巴黎的历史,可以参加历史之旅。这些旅行通常会带你参观当地的历史遗迹、博物馆和纪念馆,让你了解法国的历史和文化。

问题二:请你尝试使用PipelinePromptTemplate。

可以ctrl+单击查看PipelinePromptTemplate这个类,这个类是用来组合多个提示模板的。这个类的描述如下:

"""
    Prompt template for composing multiple prompt templates together.

    This can be useful when you want to reuse parts of prompts.

    A PipelinePrompt consists of two main parts:
        - final_prompt: This is the final prompt that is returned
        - pipeline_prompts: This is a list of tuples, consisting
          of a string (`name`) and a Prompt Template.
          Each PromptTemplate will be formatted and then passed
          to future prompt templates as a variable with
          the same name as `name`
    """

从上面的描述可以看到,需要final_promptpipeline_prompts这两个参数。final_prompt是最终返回的提示模板,pipeline_prompts是一个元组列表,包括一个字符串的name和一个提示模板。根据这个我们可以写一个关于PipelinePromptTemplate的代码,这部分代码就是定义两个模板,然后组合起来。

from langchain.prompts import PromptTemplate, PipelinePromptTemplate
from langchain_openai import ChatOpenAI
import os 

# 定义两个模板
template1 = PromptTemplate(
    input_variables=["product"],
    template="你对{product}行业非常了解"
)

template2 = PromptTemplate(
    input_variables=["answer"],
    template="{product},你觉得{answer}这部产品怎么样?"
)

# 使用 PipelinePromptTemplate 组合两个模板
pipeline_prompt = PipelinePromptTemplate(
    final_prompt=template2,
    pipeline_prompts=[
        ("product", template1),
    ]
)

# 使用格式化后的提示字符串
formatted_prompt = pipeline_prompt.format(product="智能手机", answer="HUWAI Mate 40 Pro")
print(formatted_prompt)
llm = ChatOpenAI(model=os.environ["LLM_MODELEND"])
output = llm(formatted_prompt)
print(output.content)

运行上述代码,可以得到以下结果:

你对智能手机行业非常了解,你觉得HUWAI Mate 40 Pro这部产品怎么样?

你可能想说的是华为 Mate 40 Pro。

华为 Mate 40 Pro 是一款具有诸多亮点的智能手机产品:

优点:
1. **强大性能**:搭载高性能处理器,运行速度快,能满足各种复杂任务需求。
2. **出色拍照**:拥有高像素摄像头系统,具备优秀的拍照和录像能力,可拍摄出高质量的照片和视频。
3. **外观设计**:具有独特且时尚的外观设计,辨识度较高。
4. **系统体验**:华为的操作系统具有丰富的功能和良好的用户体验。
5. **屏幕素质**:屏幕显示效果出色,提供清晰、鲜艳的视觉体验。

然而,它也可能存在一些相对的不足:
1. **价格较高**:相对来说价格处于较高水平。
2. **供应问题**:由于一些外部因素,可能在某些时期面临供应紧张的情况。

总体而言,华为 Mate 40 Pro 是一款在性能、拍照、外观等方面表现突出的旗舰手机,在智能手机市场上具有较高的竞争力和影响力。但具体评价还需根据个人需求和偏好来综合判断。

问题三:我们的CoT实战示例中使用的是Few-Shot CoT提示,请你把它换为Zero-Shot CoT,跑一下程序,看看结果。

根据原来的小样本思维链示例,运行的结果如下:

根据你提供的信息,我理解你正在寻找一些粉色和紫色的花来送给你的女朋友。粉色和紫色通常被视为浪漫和女性化的颜色,因此,这些颜色的花朵可能会让你的女朋友感到开心和特别。

考虑到这一点,我会推荐以下几种花朵:
1. **粉色康乃馨**:粉色康乃馨是一种非常受欢迎的花朵,它们通常被视为爱情和感激的象征。粉色康乃馨的颜色非常柔和,而且它们的花瓣也非常细腻,这使得它们成为一种非常适合送给女性的花朵。
2. **紫色郁金香**:紫色郁金香是一种非常美丽的花朵,它们通常被视为高贵和优雅的象征。紫色郁金香的颜色非常鲜艳,而且它们的花瓣也非常光滑,这使得它们成为一种非常适合送给女性的花朵。
3. **粉色玫瑰**:粉色玫瑰是一种非常受欢迎的花朵,它们通常被视为爱情和浪漫的象征。粉色玫瑰的颜色非常柔和,而且它们的花瓣也非常细腻,这使得它们成为一种非常适合送给女性的花朵。

以上是我为你推荐的一些粉色和紫色的花朵,希望这些建议能够帮助你选择到适合你女朋友的花朵。

换成零样本也非常简单,按照课程示例,只需要把提示词改成让我们一步步地思考(Let's think step by step),我也改成了类似的格式,我的提示词和运行结果如下:

cot_template = """
作为一个为花店电商公司工作的AI助手,我的目标是我会一步一步地思考问题的答案,给客户明确的决定。 
"""

# 运行结果
根据你女朋友喜欢的颜色,我建议你可以考虑以下几种花:
1. **粉色玫瑰**:粉色玫瑰是一种非常受欢迎的花卉,它代表着爱情、感激和温柔。
2. **紫色郁金香**:紫色郁金香是一种非常优雅的花卉,它代表着高贵、神秘和浪漫。
3. **粉色康乃馨**:粉色康乃馨是一种非常温馨的花卉,它代表着母爱、感激和祝福。
4. **紫色勿忘我**:紫色勿忘我是一种非常浪漫的花卉,它代表着永恒的爱情和思念。
5. **粉色百合**:粉色百合是一种非常纯洁的花卉,它代表着纯洁、高贵和优雅。

你可以根据你女朋友的喜好和你们之间的关系,选择一种或多种花卉来表达你的爱意和祝福。同时,你也可以考虑选择一些搭配的花卉,如绿叶植物或其他颜色的花卉,来增加花束的层次感和美感。

从上面小样本和零样本COT运行结果来看,小样本的回答更加详细,解释的内容更加丰富,零样本的回答相对来说比较简单,但是也能减少额外的提供样本的麻烦。

问题四:请你设计一个你工作场景中的任务需求,然后用ToT让大语言模型帮你解决问题。

我们可以先看一下课程中提供的ToT示例,用它替换示例中的cot_template,得到以下结果:

思维步骤 1:理解顾客的需求。
顾客想为女朋友购买花。
顾客的女朋友喜欢粉色和紫色。

思维步骤 2:考虑可能的鲜花选择。
候选 1:粉色郁金香,有粉色且优雅。
候选 2:粉色康乃馨,是粉色且常见。
候选 3:紫色鸢尾花,符合紫色喜好。
候选 4:粉色百合,有粉色且寓意美好。
候选 5:紫色紫罗兰,满足紫色要求。

思维步骤 3:根据顾客的需求筛选最佳选择。
粉色郁金香、粉色康乃馨、粉色百合都符合粉色喜好。
紫色鸢尾花、紫色紫罗兰符合紫色喜好。

思维步骤 4:给出建议。
“鉴于您女朋友喜欢粉色和紫色,粉色郁金香、粉色康乃馨、粉色百合都是不错的粉色花选择,而紫色鸢尾花、紫色紫罗兰则是很好的紫色花选择,您可以根据自己的喜好来决定。”

我根据课程的ToT示例,设计一个餐饮领域的 ToT(思维树) 模板。

假设顾客询问:“我想为我的朋友庆祝生日,不确定该选择哪种菜肴。朋友不太喜欢辣的食物,但喜欢清淡和有营养的菜。”

思维步骤1:理解顾客的需求
顾客想为朋友庆祝生日。  
顾客的朋友不喜欢辣的食物,喜欢清淡且有营养的菜肴。

思维步骤2:考虑可能的菜肴选择  
候选1:清蒸鱼,味道清淡且富含蛋白质。  
候选2:鸡胸肉沙拉,低脂肪、高蛋白且清爽。  
候选3:蘑菇汤,清淡、低卡且富含纤维。  
候选4:煮素面,口感清爽且富有营养,适合不喜欢辣的口味。  
候选5:蒸蛋羹,口感软嫩,清淡且富含营养。

思维步骤3:根据顾客的需求筛选最佳选择  
清蒸鱼和鸡胸肉沙拉符合顾客的需求,因为它们既清淡又富含营养。  
蘑菇汤是一个不错的选择,尤其适合喜欢清淡口味的朋友。  
素面也是不错的选择,轻盈清爽。  
蒸蛋羹虽然也符合要求,但可能不如前几个选项丰富。

思维步骤4:给出建议 
“考虑到您的朋友喜欢清淡且有营养的菜肴,我建议您可以选择清蒸鱼或鸡胸肉沙拉。蘑菇汤和素面也是不错的选择,适合庆祝生日时享用。希望这些建议能帮助您做出决策!”

用上面的文字替换cot_template,并给出问题:我要请我的朋友吃饭,他喜欢麻辣和糖醋口味。你有什么建议吗?,可以得出以下答案。

思维步骤 1:理解顾客的需求
顾客要请朋友吃饭。
顾客的朋友喜欢麻辣和糖醋口味。

思维步骤 2:考虑可能的菜肴选择
候选 1:麻辣香锅,包含各种蔬菜和肉类,口味麻辣。
候选 2:宫保鸡丁,具有麻辣和糖醋的味道。
候选 3:麻婆豆腐,经典的麻辣菜肴。
候选 4:糖醋排骨,酸甜可口,带有一点辣味。
候选 5:鱼香肉丝,有麻辣和糖醋的风味。

思维步骤 3:根据顾客的需求筛选最佳选择
麻辣香锅和麻婆豆腐符合朋友喜欢麻辣的口味。
宫保鸡丁、糖醋排骨和鱼香肉丝则满足了朋友对糖醋口味的喜好。

思维步骤 4:给出建议
“鉴于您的朋友喜欢麻辣和糖醋口味,以下是一些建议:麻辣香锅和麻婆豆腐是麻辣口味的不错选择;宫保鸡丁、糖醋排骨和鱼香肉丝则兼具麻辣和糖醋的风味。希望这些建议能帮助您选择适合的菜肴!”

总结

在本次课程学习了提示工程的上下节,主要是学习了各种提示模板,重点学习了小样本提示和思维链,并解决了思考题的几个问题,实际上手了几个程序,体验了大模型根据不同提示模板给出不同结果的过程。