引言
在当今人工智能迅速发展的背景下,提示工程(Prompt Engineering)作为优化大语言模型(如GPT-4)输出质量的关键技术,正受到越来越多开发者和研究者的关注。本文将带您系统了解提示工程的核心原则、策略及其在LangChain中的应用,涵盖从基础理论到实战示例,助您全面掌握这一技术。
提示工程Prompt engineering
提示工程的原则和策略
提示工程的有效性是依赖于明确的原则和策略。包括两大核心原则:
-
写出清晰而具体的指示:明确任务目标,减少歧义,使模型理解任务意图。
-
给模型思考的时间:通过分步指引或提供足够上下文,帮助模型进行复杂推理。
此外,OpenAI官方文档中提出的六大策略进一步丰富了这些原则。这些策略不仅适用于优化大语言模型的表现,也能指导人类在解决问题时的思维过程,体现了提示工程在广泛应用中的重要性。
提示结构
当然了,从大原则到实践,还是有一些具体工作需要说明,下面我们先看一个实用的提示框架。
在这个提示框架中:
指令(Instruction)
指令部分是提示的核心,它指示模型应该做什么、如何做。例如,它可以明确告知模型任务的目标、如何利用额外的信息以及如何组织输出内容。指令通常是模板中不变的部分。常见的用法如:“你是一个专业的助手,请根据以下信息为我提供帮助。”这种方式可以帮助模型准确理解自己的角色,并聚焦于任务目标。
上下文(Context)
上下文是为模型提供额外信息的部分,帮助它在执行任务时拥有更丰富的背景知识。上下文信息可以是手动输入的、通过矢量数据库检索得到的,或通过调用外部工具(如API、计算器等)获取的。这些信息使得模型能够更好地理解问题并做出精准的响应。
提示输入(Prompt Input)
提示输入部分通常是指用户提出的具体问题或要求。它明确了模型所需要完成的任务。虽然这一部分和“指令”有时可以合并,但单独提取为“提示输入”有助于模板的结构化和复用。通过将实际的输入问题作为变量传递给模板,开发者可以更方便地在不同场景下使用同一提示模板,达到灵活的提示设计效果。
输出指示器(Output Indicator)
输出指示器用来标明生成内容的开始。在某些任务中,模型需要开始生成特定类型的输出,如Python代码或文本回答,输出指示器帮助模型知道何时开始这一过程。
LangChain提示模板类型
LangChain 提供了多种提示模板,帮助开发者构建和优化与大语言模型的交互。基础的提示模板类型有两种,分别是:
- StringPromptTemplate
- ChatPromptTemplate
这两种模板可以根据需求进行扩展或组合,形成更多类型的模板,例如 FewShotPromptTemplate 和 PipelinePromptTemplate,它们分别适用于少量示例学习和处理多步流程的任务。根据任务的复杂性和要求,开发者可以灵活选择合适的模板来构建提示,从而实现更加高效的模型交互。
Few-Shot
在机器学习中,Zero-Shot、One-Shot 和 Few-Shot 这些术语指代了在极少甚至没有样本的情况下,模型学习和推理的能力。这些思想源于机器学习领域,尤其是在处理需要极少样本或没有样本的情况下,如何让模型具备“学习”的能力。
下面我们来看一下如何在LangChain中实际应用这个概念,构建出最合适的任务提示。在这个示例中,我们将使用FewShotPromptTemplate来为鲜花的广告文案生成提供帮助。
1. 创建示例样本
首先,我们需要准备一些示例数据,每个示例包含一个花卉类型、适用场合以及广告文案。通过这些示例,模型可以学习到广告文案的写作风格和结构。
samples = [
{
"flower_type": "玫瑰",
"occasion": "爱情",
"ad_copy": "玫瑰,浪漫的象征,是你向心爱的人表达爱意的最佳选择。"
},
{
"flower_type": "康乃馨",
"occasion": "母亲节",
"ad_copy": "康乃馨代表着母爱的纯洁与伟大,是母亲节赠送给母亲的完美礼物。"
},
{
"flower_type": "百合",
"occasion": "庆祝",
"ad_copy": "百合象征着纯洁与高雅,是你庆祝特殊时刻的理想选择。"
},
{
"flower_type": "向日葵",
"occasion": "鼓励",
"ad_copy": "向日葵象征着坚韧和乐观,是你鼓励亲朋好友的最好方式。"
}
]
- 创建提示模板 接下来,我们需要创建一个模板,用于将示例数据格式化为输入格式,这样模型就可以理解并生成相应的输出。
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 对象
接下来,我们将所有示例数据传递给 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="爱情"))
最后,将这个提示传递给大语言模型进行处理,生成与示例类似的新广告文案.
当我们的示例数据量变得很大时,一次性传递所有示例可能不太现实,同时也会浪费Token。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
)
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="爱情"))
通过这种方式,我们只向模型提供最相关的示例,从而减少计算资源的浪费。
COT
COT 概念
CoT的核心思想是在提示中加入思维链——即模型在生成最终答案之前,先经历一系列的推理步骤。这种做法不仅能帮助模型处理复杂问题,还能使模型的推理过程更加清晰、可追溯。
这一概念最早由谷歌大脑的Jason Wei等人于2022年提出,他们证明了给语言模型提供中间推理步骤(即“思维链”)可以显著提升模型在复杂任务中的表现。
Few-Shot CoT与Zero-Shot CoT
CoT方法有两种主要的应用形式:Few-Shot CoT和Zero-Shot CoT。
-
Few-Shot CoT: 在Few-Shot CoT中,我们通过提供几个思维链的示例来引导模型。这些示例展示了如何通过中间步骤推理出正确答案。这样,模型能够根据给定的示例模式,推断出新的问题的解决方案。
-
Zero-Shot CoT: Zero-Shot CoT则不依赖于示例,而是直接告诉模型“让我们一步步思考(Let's think step by step)”。这种方法利用模型的强大推理能力,在没有具体示例的情况下,通过简单的引导,就能帮助模型产生合理的推理结果。
使用COT构建一个AI运营助手
在下面的内容中,我们的任务是构建一个AI运营助手,帮助用户根据他们的需求选择鲜花。用户会提供一些偏好信息,AI需要按部就班地推理并给出合理的花卉建议,并解释推荐的理由。 目标:
- AI理解用户的需求;
- AI根据用户需求推荐最适合的花卉;
- AI解释为什么选择这些花卉。
CoT模板设计
为了引导AI按步骤进行推理,我们设计了一个思维链(CoT)模板,该模板帮助AI清晰地理解用户需求,并给出合理的推荐。以下是我们为花店电商AI助手设计的CoT模板:
作为一个为花店电商公司工作的AI助手,我的目标是帮助客户根据他们的喜好做出明智的决定。
我会按部就班的思考,先理解客户的需求,然后考虑各种鲜花的涵义,最后根据这个需求,给出我的推荐。
同时,我也会向客户解释我这样推荐的原因。
示例 1:
人类:我想找一种象征爱情的花。
AI:首先,我理解你正在寻找一种可以象征爱情的花。在许多文化中,红玫瑰被视为爱情的象征,这是因为它们的红色通常与热情和浓烈的感情联系在一起。因此,考虑到这一点,我会推荐红玫瑰。红玫瑰不仅能够象征爱情,同时也可以传达出强烈的感情,这是你在寻找的。
示例 2:
人类:我想要一些独特和奇特的花。
AI:从你的需求中,我理解你想要的是独一无二和引人注目的花朵。兰花是一种非常独特并且颜色鲜艳的花,它们在世界上的许多地方都被视为奢侈品和美的象征。因此,我建议你考虑兰花。选择兰花可以满足你对独特和奇特的要求,而且,兰花的美丽和它们所代表的力量和奢侈也可能会吸引你。
代码实现
接下来,我们使用LangChain框架来实现这个AI助手。LangChain是一个开源框架,旨在帮助开发人员利用大语言模型(如OpenAI GPT-4)创建基于推理的应用。我们将通过以下代码实现一个花卉推荐助手:
# 设置环境变量和API密钥
import os
os.environ["OPENAI_API_KEY"] = '你的OpenAI API Key'
# 创建聊天模型
from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(temperature=0)
# 设定 AI 的角色和目标
role_template = "你是一个为花店电商公司工作的AI助手, 你的目标是帮助客户根据他们的喜好做出明智的决定"
# CoT 的关键部分,AI 解释推理过程,并加入一些先前的对话示例(Few-Shot Learning)
cot_template = """
作为一个为花店电商公司工作的AI助手,我的目标是帮助客户根据他们的喜好做出明智的决定。
我会按部就班的思考,先理解客户的需求,然后考虑各种鲜花的涵义,最后根据这个需求,给出我的推荐。
同时,我也会向客户解释我这样推荐的原因。
示例 1:
人类:我想找一种象征爱情的花。
AI:首先,我理解你正在寻找一种可以象征爱情的花。在许多文化中,红玫瑰被视为爱情的象征,这是因为它们的红色通常与热情和浓烈的感情联系在一起。因此,考虑到这一点,我会推荐红玫瑰。红玫瑰不仅能够象征爱情,同时也可以传达出强烈的感情,这是你在寻找的。
示例 2:
人类:我想要一些独特和奇特的花。
AI:从你的需求中,我理解你想要的是独一无二和引人注目的花朵。兰花是一种非常独特并且颜色鲜艳的花,它们在世界上的许多地方都被视为奢侈品和美的象征。因此,我建议你考虑兰花。选择兰花可以满足你对独特和奇特的要求,而且,兰花的美丽和它们所代表的力量和奢侈也可能会吸引你。
"""
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)