提示工程(上):用少样本FewShotTemplate和ExampleSelector创建应景文案|豆包MarsCode AI刷题

85 阅读8分钟

GPT最佳实践6大策略

  1. 清晰的指示
  2. 给模型提供示例
  3. 将复杂任务拆分成子任务
  4. 给GPT思考时间
  5. 使用外部工具
  6. 反复迭代问题

提示的结构

  1. 指令(Instruction):告诉模型任务大概要做什么、怎么做,如使用外部信息、如何处理查询以及构造输出。常见用例:告诉模型“你是一个有用的xx助手”,这会让他更认真地对待自己的角色。
  2. 上下文(Context):模型的额外知识来源,这些信息可以手动插入到提示中,通过VectorDB检索得来,或通过其他方式(调用API、计算器等工具)拉入。常见用例:把从VectorDB查询到的知识作为上下文传递给模型。
  3. 提示输入(Prompt Input):具体的问题或需要大模型做的具体的事情,通常和“指令”部分整合。便于复用模板,通常作为变量,在调用模型之前传递给提示模板,形成具体的提示。
  4. 输出指示器(Output Indicator):标记要生成的文本的开始。如生成Python代码,可以使用“import”。LangChain中的代理在构建提示模板时,经常会用一个''Thought”(思考)作为引导词,指示模型开始输出自己的推理(Reasoning)。

LangChain提示模板的类型

LangChain中提供String(StringPromptTemplate)和Chat(BaseChatPromptTemplate)两种基本类型的模板,并基于它们构建了不同类型的提示模板:

模板导入方式如下:

from langchain.prompts.prompt import PromptTemplate
from langchain.prompts import FewShotPromptTemplate
from langchain.prompts.pipeline import PipelinePromptTemplate
from langchain.prompts import ChatPromptTemplate
from langchain.prompts import (
    ChatMessagePromptTemplate,
    SystemMessagePromptTemplate,
    AIMessagePromptTemplate,
    HumanMessagePromptTemplate,
)

有时候不指定 .prompts,直接从LangChain包也能导入模板。

from langchain import PromptTemplate

提示警告,此处最好使用langchain_core.prompts.PromptTemplate

使用 PromptTemplate

from langchain_core.prompts import PromptTemplate

template = """\
你是业务咨询顾问。
你给一个销售{product}的电商公司,起一个好的名字?
"""
prompt = PromptTemplate.from_template(template)

print(prompt.format(product="鲜花"))

输出:

你是业务咨询顾问。
你给一个销售鲜花的电商公司,起一个好的名字?

以上程序中product自动成为了format方法中的一个参数。

还可以通过提示模板类的构造函数,在创建模板时手工指定input_variables

# 创建模板时手工指定input_variables
prompt = PromptTemplate(
    input_variables=["product", "market"],
    template="你是业务咨询顾问。对于一个面向{market}市场的,专注于销售{product}的公司,你会推荐哪个名字?"
)
print(prompt.format(product="鲜花", market="高端"))

输出:

你是业务咨询顾问。对于一个面向高端市场的,专注于销售鲜花的公司,你会推荐哪个名字?

使用 ChatPromptTemplate

from langchain_core.prompts import PromptTemplate
from langchain_community.llms import Tongyi
import os


# ChatPromptTemplate
# 导入聊天消息类模板
from langchain.prompts import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)

# 模板的构建
template = "你是一位专业顾问,负责为专注于{product}的公司起名。"
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
human_template = "公司主打产品是{product_detail}。"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
prompt_template = ChatPromptTemplate.from_messages(
    [system_message_prompt, human_message_prompt]
)

# 格式化提示消息生成提示
prompt = prompt_template.format_prompt(
    product="鲜花装饰", product_detail="创新的鲜花设计。"
).to_messages()

# 下面调用模型,把提示消息传入模型,生成结果
os.environ["DASHSCOPE_API_KEY"] ='阿里的DASHSCOPE_API_KEY'
llm = Tongyi(model_name="qwen-chat", api_key=os.environ["DASHSCOPE_API_KEY"])
result = llm.invoke(prompt)
print(result)

输出

考虑到您公司的主打产品是创新的鲜花设计,以下是一些建议的公司名称:

1. 创艺花界(CreativeFloralWorld)
2. 鲜花奇境(FloralFantasy)
3. 花韵新艺(NewArtFloralRhythms)
4. 璀璨花语(BrilliantBloomWhispers)
5. 革新花饰(InnovativeFloralDecor)
6. 梦幻花匠(DreamFlorist)
7. 未来花苑(FutureFloraGarden)
8. 惊艳花艺(StunningFloralArt)
9. 魔法花境(MagicalFloralRealm)
10. 前沿花道(FrontierFloralWay)

这些名称都强调了创新和独特的设计理念,同时保持了与鲜花相关的温馨氛围。希望这些建议能够为您提供一些灵感!如果您有其他特定的需求或偏好,请随时告诉我,我会进一步调整建议。

FewShot的思想起源

Few-Shot(少样本)、One-Shot(单样本)、Zero-Shot(零样本)都来源于机器学习。让机器学习模型在极少量甚至没有示例的情况下学习到新的概念或类别,是非常有价值的,因为往往无法获取到大量的标签化的数据。

参考资料:

  1. Few-Shot Learing:一个重要的参考文献是2016年Vinyals, O.的论文《小样本学习的匹配网络》。
  2. One-Shot Learning:上述《小样本学习的匹配网络》,其中匹配网络专门针对单样本学习问题设计,可以看作是一种最常见的 Few-Shot 学习的情况。
  3. Zero-Shot Learning:一个代表性的参考文献是Palatucci, M.在2009年提出的《基于语义输出编码的零样本学习(Zero-Shot Learning with semantic output codes)》,其中的学习系统可以根据类的语义描述来识别之前未见过的类。

在提示工程(Prompt Engineering)中,

  • 在Few-Shot学习设置中,模型会被给予几个示例,以帮助模型理解任务,并生成正确的响应。
  • 在Zero-Shot学习设置中,模型只根据任务的描述生成响应,不需要任何示例

而OpenAI在介绍GPT-3模型的重要论文《Language models are Few-Shot learners(语言模型是少样本学习者)》中,指出:GPT-3模型,作为一个大型的自我监督学习模型,通过提升模型规模,实现了出色的Few-Shot学习性能

简单来说,可以通过示例的数量来区分这三类学习。

使用 FewShotPromptTemplate

1.创建示例样本

每个示例都是一个字典

# 1. 创建一些示例 字典
samples = [
    {
        "flower_type": "玫瑰",
        "occasion": "爱情",
        "ad_copy": "玫瑰,浪漫的象征,是你向心爱的人表达爱意的最佳选择。"
    },
    {
        "flower_type": "康乃馨",
        "occasion": "母亲节",
        "ad_copy": "康乃馨代表着母爱的纯洁与伟大,是母亲节赠送给母亲的完美礼物。"
    },
    {
        "flower_type": "百合",
        "occasion": "庆祝",
        "ad_copy": "百合象征着纯洁与高雅,是你庆祝特殊时刻的理想选择。"
    },
    {
        "flower_type": "向日葵",
        "occasion": "鼓励",
        "ad_copy": "向日葵象征着坚韧和乐观,是你鼓励亲朋好友的最好方式。"
    }
]

2.创建提示模板

# 2. 创建一个提示模板
template = "鲜花类型: {flower_type}\n场合: {occasion}\n文案: {ad_copy}"
prompt_sample = PromptTemplate(input_variables=["flower_type", "occasion", "ad_copy"],
                               template=template)
print(prompt_sample.format(**samples[0]))

输出

鲜花类型: 玫瑰
场合: 爱情
文案: 玫瑰,浪漫的象征,是你向心爱的人表达爱意的最佳选择。

3. 创建 FewShotPromptTemplate 对象

通过使用上一步骤中创建的prompt_sample,以及samples列表中的所有示例, 创建一个FewShotPromptTemplate对象,生成更复杂的提示。

# 3. 创建一个FewShotPromptTemplate对象
from langchain.prompts.few_shot import FewShotPromptTemplate

prompt = FewShotPromptTemplate(
    examples=samples,
    example_prompt=prompt_sample,
    suffix="鲜花类型: {flower_type}\n场合: {occasion}",
    input_variables=["flower_type", "occasion"],
)
print(prompt.format(flower_type="野玫瑰", occasion="爱情"))
鲜花类型: 玫瑰
场合: 爱情
文案: 玫瑰,浪漫的象征,是你向心爱的人表达爱意的最佳选择。

鲜花类型: 康乃馨
场合: 母亲节
文案: 康乃馨代表着母爱的纯洁与伟大,是母亲节赠送给母亲的完美礼物。

鲜花类型: 百合
场合: 庆祝
文案: 百合象征着纯洁与高雅,是你庆祝特殊时刻的理想选择。

鲜花类型: 向日葵
场合: 鼓励
文案: 向日葵象征着坚韧和乐观,是你鼓励亲朋好友的最好方式。

鲜花类型: 野玫瑰
场合: 爱情

4. 调用大模型创建新文案

# 4. 把提示传递给大模型
import os
os.environ["DASHSCOPE_API_KEY"] ='阿里的DASHSCOPE_API_KEY'
llm = Tongyi(model_name="qwen-chat", api_key=os.environ["DASHSCOPE_API_KEY"])
result = llm.invoke(prompt.format(flower_type="野玫瑰", occasion="爱情"))
print(result)

输出

鲜花类型: 野玫瑰
场合: 爱情
文案: 野玫瑰,带着一丝野性和不羁,却也充满了温柔与浪漫,它不仅代表着爱情中的热烈与真挚,还寓意着对爱情的执着追求。在特别的日子里,送一束野玫瑰给心爱的TA,让这份独特的情感传递你们之间的甜蜜与坚定吧。

使用示例选择器

由于示例很多,一次性把所有的示例发给模型是不现实且低效的。另外,每次都包含太多的token会浪费流量(大部分模型都是按照token来收取费用)。

LangChain提供了示例选择器,来选择最合适的样本。(注意,因为示例选择器使用向量相似度比较的功能,此处需要安装向量数据库,可以选择开源的Chroma,这里选择之前用过的Qdrant。)

示例选择器的示例代码。

由于示例选择器运行之后没有反应,还未找出问题,此处先使用简单的length_based_selector。

from langchain.prompts.example_selector import LengthBasedExampleSelector
length_based_selector = LengthBasedExampleSelector(
    examples=samples,
    example_prompt=prompt_sample,
    max_length=15
)
# 创建一个使用示例选择器的FewShotPromptTemplate对象
prompt = FewShotPromptTemplate(
    example_selector=length_based_selector,
    example_prompt=prompt_sample,
    suffix="鲜花类型: {flower_type}\n场合: {occasion}",
    input_variables=["flower_type", "occasion"]
)

print(prompt.format(flower_type="红玫瑰", occasion="爱情"))