LangChain实战03-提示工程|豆包MarsCode AI 刷题

145 阅读11分钟

一.前言-提示的结构

1.指令(Instuction)

告诉模型这个任务大概要做什么、怎么做,比如如何使用提供的外部信息、如何处理查询以及如何构造输出。这通常是一个提示模板中比较固定的部分。一个常见用例是告诉模型“你是一个有用的XX助手”,这会让他更认真地对待自己的角色。

2.上下文(Context)

则充当模型的额外知识来源。这些信息可以手动插入到提示中,通过矢量数据库检索得来,或通过其他方式(如调用API、计算器等工具)拉入。一个常见的用例时是把从向量数据库查询到的知识作为上下文传递给模型。

3.提示输入(Prompt Input)

通常就是具体的问题或者需要大模型做的具体事情,这个部分和“指令”部分其实也可以合二为一。但是拆分出来成为一个独立的组件,就更加结构化,便于复用模板。这通常是作为变量,在调用模型之前传递给提示模板,以形成具体的提示。

4.输出指示器(Output Indicator)

标记​​要生成的文本的开始。这就像我们小时候的数学考卷,先写一个“解”,就代表你要开始答题了。如果生成 Python 代码,可以使用 “import” 向模型表明它必须开始编写 Python 代码(因为大多数 Python 脚本以import开头)。这部分在我们和ChatGPT对话时往往是可有可无的,当然LangChain中的代理在构建提示模板时,经常性的会用一个“Thought:”(思考)作为引导词,指示模型开始输出自己的推理(Reasoning)。

二.提示模板类型

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

image.png 模板导入可以分别写代码也可以直接引用from langchain import PromptTemplate。 下面我们通过示例来介绍模版,前两个简单了解,最典型的FewShotPromptTemplate会重点讲。

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="鲜花"))

只要我们先创建一个初始模板,然后通过PromptTemplatefrom_template方法,我们就创建了一个提示模板对象(里面的变量product会自动提取),并通过prompt.format方法将模板中的 {product} 替换为 "鲜花"。

当然我们也可以手动输入变量

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

这里我们自己给出了input_variables变量,而没有使用PromptTemplatefrom_template方法。

四.使用 ChatPromptTemplate

在前面文章中写过直接调用OpenAI的chat模型的messages包含rolecontent,代码如下:

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
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI()
result = chat(prompt)
print(result)

观察这段代码,首先引用SystemMessagePromptTemplate其实就相当于构建system及它的content;引用HumanMessagePromptTemplate就相当于构造user及它的content。然后分别利用from_templete方法构造两种提示模板对象,再利用ChatPromptTemplatefrom_messages方法将两种模板合成一个,最后填充模板形成提示。在生成提示后,就可以调用模型输出结果了。

五.使用 FewShotPromptTemplate

(1).原理

Few-Shot即为少样本,在Few-Shot学习设置中,模型会被给予几个示例,以帮助模型理解任务,并生成正确的响应。

(2).实现

1.创建示例样本

每个示例都是一个字典。键是输入变量,值是这些输入变量的值。下面给出一个示例,若是想多加几个示例直接在后面复制粘贴然后修改变量即可。

samples = [
  {
    "flower_type": "玫瑰",
    "occasion": "爱情",
    "ad_copy": "玫瑰,浪漫的象征,是你向心爱的人表达爱意的最佳选择。"
  },
]

samples这个列表,它包含了四个字典,每个字典代表了一种花的类型、适合的场合,以及对应的广告文案。 这些示例样本,就是构建FewShotPrompt时,作为例子传递给模型的参考信息。

2.创建提示模板

到这里,我们就把字典中的示例格式转换成了提示模板,可以形成一个个具体可用的LangChain提示。比如用samples[0]中的数据替换了模板中的变量,生成了一个完整的提示。这里我们采用的是直接提供输入变量input_variables

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

如果在samples字典中含有好几个示例,并且我们想将其它示例填充进模板,就可以修改sample[i]中的i,并且下标从0开始,这里还是比较好理解的。

3.创建 FewShotPromptTemplate 对象

通过使用上一步骤中创建的prompt_sample,以及samples列表中的所有示例, 创建一个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="爱情"))

这里创建了一个对象prompt,其中examples用于接收示例,example_prompt用于定义示例的提示格式。

suffix设定了最终文本呈现的基本格式框架(包含需要替换的占位符),而input_variables则告诉程序哪些占位符对应的变量是需要从外部传入值来进行替换的,二者配合来实现灵活生成符合特定格式要求的文本内容的功能。在后面我们只要提供suffix就可以获得最终的广告文案ad_copy

4. 调用大模型创建新文案
import os
from langchain.llms import OpenAI
model = OpenAI(model_name='gpt-3.5-turbo-instruct')
result = model(prompt.format(flower_type="野玫瑰", occasion="爱情"))
print(result)

这里调用模型输出结果,方法在前面的文章中也具体写过了。

(3)使用示例选择器

如果我们的示例很多,那么一次性把所有示例发送给模型是不现实而且低效的。LangChain给我们提供了示例选择器,来选择最合适的样本。下面,就是使用示例选择器的示例代码:

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 来创建一个更智能的 FewShotPromptTemplate 对象。它会根据语义相似度从示例中选择与当前输入最相关的示例。

代码中创建了一个示例选择器example_selector。并且传入了samples(示例数据),OpenAIEmbeddings()(用于将文本转换为向量)和 Chroma(向量存储类型),并且设置 k = 1 ,这意味着选择器将选择与输入语义最相似的 1 个示例。最后创建一个使用示例选择器的FewShotPromptTemplate对象,它能够从多个示例中选取最接近我们所提供的示例来获取输出。

小册中没有给出输出结果,在AI练中学的代码中我们可以摘录出这部分代码,看看输入的野玫瑰能有怎么样的输出:

import os
from langchain_openai import ChatOpenAI

model=ChatOpenAI(os.environ.get["LLM_MOODLEND"])
result=model(prompt.format(flower_type="红玫瑰", occasion="爱情")

print(result)

我们来看看输出结果:

屏幕截图 2024-11-13 202034.png

六.Chain of Thought(CoT)

(1)初识CoT:

Chain of Thought,即思维链。CoT这个概念提出,如果生成一系列的中间推理步骤,就能够显著提高大型语言模型进行复杂推理的能力。

1.Few-Shot CoT

Few-Shot CoT 简单的在提示中提供了一些链式思考示例(Chain-of-Thought Prompting),足够大的语言模型的推理能力就能够被增强。简单说,就是给出一两个示例,然后在示例中写清楚推导的过程。举个例子就很清楚了:

image.png 我们可以看到在过程中我们添加了一项思维链,将从输入到输出的思考过程提供给模型,就能得出更准确的结果。

其实LangChain的核心组件Agent的本质就是进行好的提示工程,并大量地使用预置的FewShot和CoT模板。

2.Zero-Shot CoT

我们再来看一个示例:

image.png 我们只要简单地告诉模型“让我们一步步的思考(Let's think step by step)”,模型就能够给出更好的答案。Zero-Shot CoT的本质就是直接告诉模型要一步一步地思考,慢慢地推理。

(2)实战

项目需求:在这个示例中,你正在开发一个AI运营助手,我们要展示AI如何根据用户的需求推理和生成答案。然后,AI根据当前的用户请求进行推理,提供了具体的花卉建议并解释了为什么选择这些建议。

1.构造模型
import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model=os.environ.get("LLM_MODELEND"),
)
2.设定AI的角色和目标
role_template = "你是一个为花店电商公司工作的AI助手, 你的目标是帮助客户根据他们的喜好做出明智的决定"
3.构建思维链

CoT 的关键部分,AI 解释推理过程,并加入一些先前的对话示例(Few-Shot Learning)

cot_template = """
作为一个为花店电商公司工作的AI助手,我的目标是帮助客户根据他们的喜好做出明智的决定。 

我会按部就班的思考,先理解客户的需求,然后考虑各种鲜花的涵义,最后根据这个需求,给出我的推荐。
同时,我也会向客户解释我这样推荐的原因。

示例 1:
  人类:我想找一种象征爱情的花。
  AI:首先,我理解你正在寻找一种可以象征爱情的花。在许多文化中,红玫瑰被视为爱情的象征,这是因为它们的红色通常与热情和浓烈的感情联系在一起。因此,考虑到这一点,我会推荐红玫瑰。红玫瑰不仅能够象征爱情,同时也可以传达出强烈的感情,这是你在寻找的。

示例 2:
  人类:我想要一些独特和奇特的花。
  AI:从你的需求中,我理解你想要的是独一无二和引人注目的花朵。兰花是一种非常独特并且颜色鲜艳的花,它们在世界上的许多地方都被视为奢侈品和美的象征。因此,我建议你考虑兰花。选择兰花可以满足你对独特和奇特的要求,而且,兰花的美丽和它们所代表的力量和奢侈也可能会吸引你。
"""
4.创建提示模板

这里我们利用上面学的ChatPromptTemplate来获取结果。

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

system_prompt_role = SystemMessagePromptTemplate.from_template(role_template)
system_prompt_cot = SystemMessagePromptTemplate.from_template(cot_template)

# 用户的询问
human_template = "{human_input}"
human_prompt = HumanMessagePromptTemplate.from_template(human_template)

# 将以上所有信息结合为一个聊天提示
chat_prompt = ChatPromptTemplate.from_messages(
    [system_prompt_role, system_prompt_cot, human_prompt]
)

prompt = chat_prompt.format_prompt(
    human_input="我想为我的女朋友购买一些花。她喜欢粉色和紫色。你有什么建议吗?"
).to_messages()

# 接收用户的询问,返回回答结果
response = llm(prompt)
print(response)

这里创建了三个提示模板:system_prompt_role用于定义AI的角色,system_prompt_cot用于定义思维链,human_prompt用于获取用户的输入。然后,将这三个模板组合成一个聊天提示模板chat_prompt。最后调用模型获取输出结果。

那么以上就是提示模板所有的学习内容了。