提示工程 | 豆包MarsCode AI刷题

188 阅读13分钟

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

使用 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="高端"))

解释如下:

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

这里定义了一个字符串模板,其中包含了一个占位符 {product}。这个模板描述了一个任务,即要求以业务咨询顾问的角色,为销售特定产品(由 {product} 占位符表示,后续会代入具体产品名称)的电商公司起一个好名字。

prompt = PromptTemplate.from_template(template)

这行代码使用 from_template 方法根据前面定义的 template 字符串创建了一个 PromptTemplate 对象。这个对象会解析模板字符串中的占位符等格式信息,以便后续进行格式化操作。

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

这里通过直接实例化 PromptTemplate 类来创建一个新的提示模板对象。在实例化时,指定了 input_variables 参数为一个包含 "product" 和 "market" 的列表,这表示模板字符串中会有这两个占位符。模板字符串描述的任务是让业务咨询顾问为面向特定市场({market} 占位符)且专注于销售特定产品({product} 占位符)的公司推荐一个名字。

print(prompt.format(product="鲜花", market="高端"))

调用 prompt 对象的 format 方法,这次传入了 "product" 为 "鲜花" 和 "market" 为 "高端" 的值,这样就会把模板中的 {product} 和 {market} 占位符分别替换为对应的具体值,然后打印出格式化后的提示文本,大致内容会是 "你是业务咨询顾问。对于一个面向高端市场的,专注于销售鲜花的公司,你会推荐哪个名字?"

使用 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 API Key'

from langchain_openai import ChatOpenAI

chat = ChatOpenAI(
    model=os.environ.get("LLM_MODELEND"),
)
result = chat(prompt)
print(result)

代码解释:

from langchain.prompts import ( ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate, )

这段代码从 langchain.prompts 模块中导入了三个重要的类:

  • ChatPromptTemplate:用于构建适合与聊天模型(如 ChatGPT 等)进行交互的提示模板。它可以组合多种不同类型的消息模板(如系统消息、人类消息等)来形成一个完整的聊天提示。
  • SystemMessagePromptTemplate:专门用于创建系统消息的提示模板。系统消息通常用于给聊天模型设定一些背景、角色、任务等方面的上下文信息。
  • HumanMessagePromptTemplate:用于创建人类用户发送的消息的提示模板,模拟人类向聊天模型提出问题或给出相关信息的场景。
template = "你是一位专业顾问,负责为专注于{product}的公司起名。" system_message_prompt = SystemMessagePromptTemplate.from_template(template)

首先定义了一个字符串模板 template,其中包含了占位符 {product}。这个模板描述了一个角色设定,即作为一名专业顾问,任务是为专注于特定产品的公司起名。然后通过 SystemMessagePromptTemplate.from_template 方法,根据这个模板创建了系统消息提示模板对象 system_message_prompt。这个对象后续会作为聊天提示中的系统消息部分,用于给聊天模型设定任务背景。

human_template = "公司主打产品是{product_detail}。" human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)

类似地,定义了另一个字符串模板 human_template,包含占位符 {product_detail}。该模板用于说明公司主打产品的具体情况。通过 HumanMessagePromptTemplate.from_template 方法,依据这个模板创建了人类消息提示模板对象 human_message_prompt。这个对象将模拟人类向聊天模型提供关于公司主打产品的详细信息。

prompt_template = ChatPromptTemplate.from_messages( [system_message_prompt, human_message_prompt] )

这里使用 ChatPromptTemplate.from_messages 方法,将前面创建的系统消息提示模板 system_message_prompt 和人类消息提示模板 human_message_prompt 组合起来,形成一个完整的聊天提示模板对象 prompt_template。这样的组合方式符合与聊天模型交互的常见场景,先通过系统消息设定任务背景,再通过人类消息提供具体细节。

prompt = prompt_template.format_prompt( product="鲜花装饰", product_detail="创新的鲜花设计。" ).to_messages()

调用 prompt_template 的 format_prompt 方法,传入具体的值来填充占位符。这里将 product 的值设为 "鲜花装饰",product_detail 的值设为 "创新的鲜花设计。",这样就会把模板中的占位符替换为相应的具体内容,然后通过 .to_messages() 方法将格式化后的提示转换为适合聊天模型接收的消息格式(通常是一个包含系统消息和人类消息的列表形式)。

使用 FewShotPromptTemplate

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

__import__("pysqlite3")
import sys

sys.modules["sqlite3"] = sys.modules.pop("pysqlite3")

# 2. 创建一个提示模板
from langchain.prompts.prompt import PromptTemplate

prompt_sample = PromptTemplate(
    input_variables=["flower_type", "occasion", "ad_copy"],
    template="鲜花类型: {flower_type}\n场合: {occasion}\n文案: {ad_copy}",
)
print(prompt_sample.format(**samples[0]))

# 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. 把提示传递给大模型
import os

# os.environ["OPENAI_API_KEY"] = '你的OpenAI API Key'
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    model=os.environ.get("LLM_MODELEND"),
)
result = model(prompt.format(flower_type="野玫瑰", occasion="爱情"))
print(result)

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

# 初始化Embedding类
from volcenginesdkarkruntime import Ark
from typing import List, Any
from langchain.embeddings.base import Embeddings
from langchain.pydantic_v1 import BaseModel


class DoubaoEmbeddings(BaseModel, Embeddings):
    client: Ark = None
    api_key: str = ""
    model: str

    def __init__(self, **data: Any):
        super().__init__(**data)
        if self.api_key == "":
            self.api_key = os.environ["OPENAI_API_KEY"]
        self.client = Ark(
            base_url=os.environ["OPENAI_BASE_URL"],
            api_key=self.api_key
        )

    def embed_query(self, text: str) -> List[float]:
        """
        生成输入文本的 embedding.
        Args:
            texts (str): 要生成 embedding 的文本.
        Return:
            embeddings (List[float]): 输入文本的 embedding,一个浮点数值列表.
        """
        embeddings = self.client.embeddings.create(model=self.model, input=text)
        return embeddings.data[0].embedding

    def embed_documents(self, texts: List[str]) -> List[List[float]]:
        return [self.embed_query(text) for text in texts]

    class Config:
        arbitrary_types_allowed = True


# 初始化示例选择器
example_selector = SemanticSimilarityExampleSelector.from_examples(
    samples,
    DoubaoEmbeddings(
        model=os.environ.get("EMBEDDING_MODELEND"),
    ),
    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="爱情"))

代码解释:

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

这里创建了一个包含多个字典元素的列表 samples,每个字典表示一种鲜花的信息,包括鲜花类型(flower_type)、适用场合(occasion)以及对应的广告文案(ad_copy)。这些示例数据将用于后续的提示模板构建和示例选择等操作。

from langchain.prompts.prompt import PromptTemplate prompt_sample = PromptTemplate( input_variables=["flower_type", "occasion", "ad_copy"], template="鲜花类型: {flower_type}\n场合: {occasion}\n文案: {ad_copy}", ) print(prompt_sample.format(**samples[0]))

从 langchain.prompts.prompt 模块导入 PromptTemplate 类,用于创建提示模板。定义了一个 PromptTemplate 对象 prompt_sample,指定了输入变量为 flower_typeoccasion 和 ad_copy,模板字符串则按照特定格式展示这些变量信息。最后通过 format 方法,传入 samples 列表中的第一个字典元素(使用 ** 解包字典),将模板中的占位符替换为实际值并打印出来,展示了如何根据示例数据格式化提示模板。

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

从 langchain.prompts.few_shot 模块导入 FewShotPromptTemplate 类,用于创建基于少量示例的提示模板。创建了一个 FewShotPromptTemplate 对象 prompt,指定了示例数据为 samples,每个示例的提示模板为 prompt_sample,还定义了一个后缀字符串(suffix),该字符串在最后生成的提示中会出现在示例之后,并且指定了输入变量为 flower_type 和 occasion。最后通过 format 方法传入特定的 flower_type 和 occasion 值,生成并打印完整的提示信息,这个提示信息将包含示例数据以及根据输入值生成的特定部分,可用于后续提供给大模型作为输入上下文。

from volcenginesdkarkruntime import Ark from typing import List, Any from langchain.embeddings.base import Embeddings from langchain.pydantic_v1 import BaseModel class DoubaoEmbeddings(BaseModel, Embeddings): client: Ark = None api_key: str = "" model: str def __init__(self, **data: Any): super().__init__(**data) if self.api_key == "": self.api_key = os.environ["OPENAI_API_KEY"] self.client = Ark( base_url=os.environ["OPENAI_BASE_URL"], api_key=self.api_key ) def embed_query(self, text: str) -> List[float]: """ 生成输入文本的 embedding. Args: texts (str): 要生成 embedding 的文本. Return: embeddings (List[float]): 输入文本的 embedding,一个浮点数值列表. """ embeddings = self.client.embeddings.create(model=self.model, input=text) return embeddings.data[0].embedding def embed_documents(self, texts: List[str]) -> List[List[float]]: return [self.embed_query(text) for text in texts] class Config: arbitrary_types_allowed = True

这个类定义了一个名为 DoubaoEmbeddings 的自定义嵌入类,它继承自 BaseModel 和 Embeddings。在类的初始化方法中,尝试获取 OpenAI_API_KEY 环境变量作为 api_key,并根据 OpenAI_BASE_URL 环境变量创建一个 Ark 客户端对象。类中还定义了 embed_query 和 embed_documents 方法,用于生成文本的嵌入向量。

from langchain.prompts.example_selector import SemanticSimilarityExampleSelector from langchain_community.vectorstores import Chroma # 初始化Embedding类 # (前面已定义 DoubaoEmbeddings 类) example_selector = SemanticSimilarityExampleSelector.from_examples( samples, DoubaoEmbeddings( model=os.environ.get("EMBEDDING_MODELEND"), ), Chroma, k=1, )

从 langchain.prompts.example_selector 导入 SemanticSimilarityExampleSelector 类,从 langchain_community.vectorstores 导入 Chroma 类(可能用于向量存储相关操作)。然后使用 SemanticSimilarityExampleSelector.from_examples 方法创建一个示例选择器对象 example_selector,传入示例数据 samples、自定义的嵌入类 DoubaoEmbeddings(传入了一个可能错误的模型名称变量 os.environ.get("EMBEDDING_MODELEND"))以及 Chroma 对象,并指定 k=1,表示只选择最相似的一个示例。

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

建一个新的 FewShotPromptTemplate 对象 prompt,这次使用了前面创建的示例选择器 example_selector,以及之前定义的示例提示模板 prompt_sample 和后缀字符串,指定了输入变量。最后通过 format 方法传入特定的 flower_type 和 occasion 值,生成并打印提示信息。由于示例选择器会根据嵌入向量和语义相似性选择示例,这次生成的提示信息可能只包含与 "红玫瑰" 和 "爱情" 最相似的示例数据以及相应的格式化部分。

使用示例选择器

# 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="爱情"))
  • SemanticSimilarityExampleSelector.from_examples 方法用于创建示例选择器对象。

  • 第一个参数 samples 是之前定义的示例数据列表,包含不同鲜花的类型、场合和广告文案信息。

  • 第二个参数 OpenAIEmbeddings() 创建了一个 OpenAIEmbeddings 实例,用于将示例文本转换为向量表示,以便进行语义相似度计算。

  • 第三个参数 Chroma 是向量存储库类,用于存储示例文本的向量表示并进行相似度搜索。这里没有对 Chroma 进行进一步的初始化配置(如指定数据库路径等),可能使用其默认设置或在其他地方有相关配置。

  • k=1 表示只选择与目标最相似的一个示例。

  • 创建一个 FewShotPromptTemplate 对象 prompt

    • example_selector=example_selector 指定了使用前面创建的示例选择器来确定要包含在提示中的示例。
    • example_prompt=prompt_sample 是之前定义的示例提示模板,用于格式化每个示例的展示方式。
    • suffix="鲜花类型: {flower_type}\n场合: {occasion}" 定义了在示例之后添加的固定后缀内容,其中包含占位符,用于根据输入变量进行格式化。
    • input_variables=["flower_type", "occasion"] 列出了需要用户提供值来格式化模板的变量。

思考题

请你构想一个关于鲜花店运营场景中客户服务对话的少样本学习任务。在这个任务中,模型需要根据提供的示例,学习如何解答客户的各种问题,包括询问花的价格、推荐鲜花、了解鲜花的保养方法等。最好是用ChatModel完成这个任务。

from langchain.prompts import FewShotPromptTemplate, ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate
from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain_openai import ChatOpenAI
import os

# 设置 OpenAI API 密钥
os.environ["OPENAI_API_KEY"] = "YOUR_API_KEY"

# 示例数据
samples = [
    {
        "question": "玫瑰多少钱一束?",
        "answer": "玫瑰的价格因品种和季节而异,普通红玫瑰一束大概在 200 - 500 元之间。"
    },
    {
        "question": "我想送朋友生日,推荐什么花?",
        "answer": "生日送花可以选择向日葵,它代表着阳光和活力,很适合用来祝福朋友。或者百合也不错,象征着纯洁美好。"
    },
    {
        "question": "鲜花怎么保养?",
        "answer": "鲜花保养需要将花茎斜切,放在干净的花瓶中,加入适量清水,并定期换水,避免阳光直射和风口直吹。"
    }
]

# 构建系统消息提示模板
system_template = "你是鲜花店的专业客服,需要回答客户关于鲜花的各种问题。"
system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)

# 构建人类消息提示模板(用于示例)
human_template = "问题: {question}\n回答: {answer}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)

# 构建示例选择器
example_selector = SemanticSimilarityExampleSelector.from_examples(
    samples,
    OpenAIEmbeddings(),
    Chroma,
    k=1
)

# 构建 FewShotPromptTemplate
prompt = FewShotPromptTemplate(
    example_selector=example_selector,
    example_prompt=human_message_prompt,
    suffix="问题: {user_question}",
    input_variables=["user_question"]
)

# 创建 ChatOpenAI 模型实例
chat = ChatOpenAI()

# 模拟客户问题
user_question = "百合多少钱一束?"

# 生成提示并获取模型回答
formatted_prompt = prompt.format(user_question=user_question)
messages = ChatPromptTemplate.from_messages([system_message_prompt, formatted_prompt])
response = chat(messages.format_prompt().to_messages())

print(response)