提示工程(上)| 豆包MarsCode AI 刷题

54 阅读8分钟

提示工程该怎么做,策略如下:

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

提示的结构

下面是一个实用的提示框架:

image.png

在这个提示框架中:

  • 指令(Instuction)告诉模型这个任务大概要做什么、怎么做,比如如何使用提供的外部信息、如何处理查询以及如何构造输出。这通常是一个提示模板中比较固定的部分。一个常见用例是告诉模型“你是一个有用的XX助手”,这会让他更认真地对待自己的角色。
  • 上下文(Context)则充当模型的额外知识来源。这些信息可以手动插入到提示中,通过矢量数据库检索得来,或通过其他方式(如调用API、计算器等工具)拉入。一个常见的用例时是把从向量数据库查询到的知识作为上下文传递给模型。
  • 提示输入(Prompt Input)通常就是具体的问题或者需要大模型做的具体事情,这个部分和“指令”部分其实也可以合二为一。但是拆分出来成为一个独立的组件,就更加结构化,便于复用模板。这通常是作为变量,在调用模型之前传递给提示模板,以形成具体的提示。
  • 输出指示器(Output Indicator)标记要生成的文本的开始。这就像我们小时候的数学考卷,先写一个“解”,就代表你要开始答题了。如果生成 Python 代码,可以使用 “import” 向模型表明它必须开始编写 Python 代码(因为大多数 Python 脚本以import开头)。这部分在我们和ChatGPT对话时往往是可有可无的,当然LangChain中的代理在构建提示模板时,经常性的会用一个“Thought:”(思考)作为引导词,指示模型开始输出自己的推理(Reasoning)。

LangChain 提示模版的类型

LangChain提供两种基本类型的模版 (String&Chat),并基于这两个构建了不同类型的提示模版:

image.png

模版的导入方式如下:


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,
)

PromptTemplate

调用方式一(更方便)

from langchain import PromptTemplate

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

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

调用方式二

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

ChatPromptTemplate

OpenAI调用ChatPrompt的形式

import openai
openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Who won the world series in 2020?"},
        {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
        {"role": "user", "content": "Where was it played?"}
    ]
)

LangChain调用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()

# 下面调用模型,把提示传入模型,生成结果
import os
os.environ["OPENAI_API_KEY"] = '你的OpenAI Key'
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI()
result = chat(prompt)
print(result)

输出:

content='1. 花语创意\n2. 花韵设计\n3. 花艺创新\n4. 花漾装饰\n5. 花语装点\n6. 花翩翩\n7. 花语之美\n8. 花馥馥\n9. 花语时尚\n10. 花之魅力' 
additional_kwargs={} 
example=False

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. 创建一个提示模板
from langchain.prompts.prompt import PromptTemplate
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对象

# 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="爱情"))

suffix是紧跟的新提示,在固定的sample下能够自定义后续的prompt。

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

# 4. 把提示传递给大模型
import os
os.environ["OPENAI_API_KEY"] = '你的Open AI Key'
from langchain.llms import OpenAI
model = OpenAI(model_name='gpt-3.5-turbo-instruct')
result = model(prompt.format(flower_type="野玫瑰", occasion="爱情"))
print(result)

输出:

文案: 野玫瑰代表着爱情的坚贞,是你向心爱的人表达爱意的最佳礼物。

5. 示例选择器

# 5. 使用示例选择器
from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

# 初始化示例选择器
example_selector = SemanticSimilarityExampleSelector.from_examples(
    samples,
    OpenAIEmbeddings(),
    Chroma,
    k=1
)

# 创建一个使用示例选择器的FewShotPromptTemplate对象
prompt = FewShotPromptTemplate(
    example_selector=example_selector, 
    example_prompt=prompt_sample, 
    suffix="鲜花类型: {flower_type}\n场合: {occasion}", 
    input_variables=["flower_type", "occasion"]
)
print(prompt.format(flower_type="红玫瑰", occasion="爱情"))

示例选择有可能有效果有可能没有效果,有的文章随机选择示例和按相似度选择示例的表现差不多。

思考题

  1. 如果你观察LangChain中的prompt.py中的PromptTemplate的实现代码,你会发现除了我们使用过的input_variables、template等初始化参数之外,还有template_format、validate_template等参数。举例来说,template_format可以指定除了f-string之外,其它格式的模板,比如jinja2。请你查看LangChain文档,并尝试使用这些参数。

    template_format: str = "f-string"
    """The format of the prompt template. Options are: 'f-string', 'jinja2'."""
    
    validate_template: bool = True
    """Whether or not to try validating the template."""
    

    示例1 使用template_format参数:

    from langchain.prompts import PromptTemplate
    
    template = "你是一名专业顾问,你的建议是:{{ advice }}"
    prompt = PromptTemplate(
        input_variables=["advice"],
        template=template,
        template_format="jinja2"
    )
    
    formatted_prompt = prompt.format(advice="给公司起个创新的名字")
    print(formatted_prompt)
    

    输出:

    你是一名专业顾问,你的建议是:给公司起个创新的名字
    

    示例2 使用validate_template参数:

    prompt = PromptTemplate(
        input_variables=["name"],
        template="Hello, {name}",
        validate_template=False
    )
    print(prompt.format(name="Alice"))
    

    这个参数适用于模版变量动态生成,不确定输入内容是否符合template等情况。

  2. 请你尝试使用PipelinePromptTemplate和自定义Template。

    from langchain.prompts.pipeline import PipelinePromptTemplate
    from langchain.prompts import PromptTemplate
    
    template1 = PromptTemplate(
        input_variables=["product"],
        template="你是一名专业顾问,负责为销售{product}的公司提供建议。"
    )
    
    template2 = PromptTemplate(
        input_variables=["target_market"],
        template="对于目标市场是{target_market}的公司,你会建议什么?"
    )
    
    final_prompt = PromptTemplate(
        input_variables=["product_prompt", "market_prompt"],
        template='*'*50+"\n{product_prompt}\n{market_prompt}\n"+'*'*50
    )
    
    pipeline_template = PipelinePromptTemplate(
        pipeline_prompts=[("product_prompt", template1), ("market_prompt", template2)],
        final_prompt=final_prompt
    )
    
    formatted_prompt = pipeline_template.format(product="鲜花", target_market="高端市场")
    print(formatted_prompt)
    
  3. 请你构想一个关于鲜花店运营场景中客户服务对话的少样本学习任务。在这个任务中,模型需要根据提供的示例,学习如何解答客户的各种问题,包括询问花的价格、推荐鲜花、了解鲜花的保养方法等。最好是用ChatModel完成这个任务。

    from langchain.chat_models import ChatOpenAI
    from langchain import PromptTemplate
    from langchain.prompts.chat import (
        ChatPromptTemplate,
        SystemMessagePromptTemplate,
        AIMessagePromptTemplate,
        HumanMessagePromptTemplate)
    
    samples=[
        {
            "customer_query": "请问玫瑰花的价格是多少?",
            "response": "您好!玫瑰花的价格根据品种和数量不同,单支价格为10元起。如果您需要特别的品种或包装,可以联系我们详细了解哦!"
        },
        {
            "customer_query": "您能推荐一些适合送给朋友的花吗?",
            "response": "推荐您选择向日葵或康乃馨,象征友谊和祝福,非常适合送给朋友。如果想了解更多搭配,我们很乐意为您提供帮助!"
        },
        {
            "customer_query": "百合花该怎么保养呢?",
            "response": "百合花保养时,请保持清水,每天换水,同时避免阳光直射。可以适当修剪花茎,延长花期。"
        }
    ]
    
    from langchain_core.prompts import PromptTemplate,FewShotPromptTemplate
    from langchain.prompts import ChatPromptTemplate,SystemMessagePromptTemplate,HumanMessagePromptTemplate
    
    # 定义单个sample的prompt
    template="客户问题: {customer_query}\n客服回复: {response}"
    prompt_sample=PromptTemplate.from_template(template)
    
    # 定义few-shot的prompt
    few_shot_prompt=FewShotPromptTemplate(
        examples=samples,
        example_prompt=prompt_sample,
        suffix="客户问题: {customer_query}",
        input_variables=["customer_query"]
    )
    
    customer_query="您能推荐一些适合送给长辈的花吗?"
    few_shot_text=few_shot_prompt.format(customer_query=customer_query)
    
    # 由于要采用chat模式,所以few-shot的prompt要通过用户提供
    chat_prompt_template=ChatPromptTemplate.from_messages([
        SystemMessagePromptTemplate.from_template("你是一个鲜花店的运营客服,擅长解答客户的各种问题,包括询问花的价格、推荐鲜花、了解鲜花的保养方法等。"),
        HumanMessagePromptTemplate.from_template("{few_shot_prompt}")
    ])
    
    prompt=chat_prompt_template.format_prompt(few_shot_prompt=few_shot_text)
    
    import os
    from langchain_openai import ChatOpenAI
    chat = ChatOpenAI(
        model=os.environ.get("LLM_MODELEND")
    )
    result = chat(prompt)
    print(result)