模型/O功能之提示词模板

文章目录

模型/O功能之提示词模板

在LangChain框架中,提示词不是简单的字符串,而是一个更复杂的结构,是一个"提示词工程"。这个结构中包含一个或多个提示词模板(PromptTemplate类的实例),每个提示词模板可以接收一些输人变量,并根据这些变量生成对应的提示词,这样就可以根据具体的需求和情境动态地创建各种各样的提示词。这就是提示词模板的核心思想和工作方式。

例如,可能有一个提示词模板用于生成写邮件时的提示词,这个模板需要接收如收件人、主题、邮件内容等输人变量,然后根据这些变量生成如"写一封给{收件人}的邮件,主题是{主题},内容是{邮件内容}"这样的提示词模板字符串。这种工程化的提示词构造方式,可以产出适用于各种应用程序的内容,而不仅仅是简单的聊天内容。复杂的提示词可以用于生成文章、编写邮件、回答问题、执行任务等各种场景,大大提高了大语言模型的实用性和可用性。

什么是提示词模板

提示词可以被视为向大语言模型提出的请求,它们表明了使用者希望模型给出何种反应。提示词的质量直接影响模型的回答质量,决定了模型能否成功完成更复杂的任务。在LangChain框架中,提示词是由"提示词模板"(PromptTemplate)这个包装器对象生成的。每一个PromptTemplate类的实例都定义了一种特定类型的提示词格式和生成规则。在LangChain中,要想构造提示词,就必须学会使用这个包装器对象。

你可以将提示词模板视为一个幕后工作者,它在幕后默默地工作,用户只看到他们自己输入的简单关键词,却得到了模型给出的出色响应。这是因为开发者将用户的输人嵌人了预先设计好的提示词模板中,这个模板就是一个包装器,用户的输人经过包装器的包装后,最终变成一个高效的提示词被输出。这个包装器还能组合不同的提示词,提供各种格式化、参数检验工具,帮助开发者构造复杂的提示词。

提示词模板是一种可复制、可重用的生成提示词的工具,是用于生成提示词的模板字符串,其中包含占位符,这些占位符可以在运行时被动态替换成实际终端用户输入的值,其中可以插人变量、表达式或函数的结果。提示词模板中可能包含(不是必须包含)以下3个元素。

  1. 明确的指令:这些指令可以指导大语言模型理解用户的需求,并按照特定的方式进行回应,见下图中的"明确的指令"。
  2. 少量示例:这些示例可以帮助大语言模型更好地理解任务,并生成更准确的响应,见下图中的"少量示例"。
  3. 用户输入:用户的输人可以直接引导大语言模型生成特定的答案,见下图中的"用户输人"。

通过灵活使用这些元素创建新的提示词模板,可以更有效地利用大语言模型的能力,提高其在各种应用场景下的表现。提示词模板可批量生成提示词,它可以接收开发者对任务的描述文本,也可以接收用户输入的一系列参数。比如,要给公司的产品取一个好听的名字,用户输人的是产品的品类名,如"袜子""毛巾"、然而我们并不需要为每一个品类都编写一个提示词,使用提示词模板,根据用户输人的不同品类名生成对应的提示词即可:"请给公司的{品类名},取一个简单且容易传播的产品名字"提示词模板的职责就是根据大语言模型平台的API类型,包装并生成适合的提示词。

为了满足不同类型模型平台底层API的需求,提示词模板提供了format方法和format prompt方法,输出可以是字符串、消息列表,以及ChatPrompt Value形式。比如对于需要输入字符串的LLM模型包装器、提示词模板会使用to string方法将提示词转化为一个字符串。而对于需要输入消息列表的聊天模型包装器,提示词模板则会使用to_messages方法将提示词转化为一个消息列表总的来说、提示词模板就是一种能够产生动态提示词的包装器,开发者将数据输入包装器,经过包装后,输出的是适配各个模型平台的提示词。

提示词模板的输入和输出

如前所述,提示词模板是一个输入数据并输出提示词的句装器。那么开发者可以向他输入什么样的数据呢?具体的输出是什么呢?

内部数据是指那些已经被LangChain框架封装好的数据,以及开发者写的示例和需求描述文本(下图中的"明确的指令"和"少量示例")。比如,LangChain的许多Agent和Chain实例对象都内置了自己的提示词。这些提示词都被预先定义在源码prompt...py文件中,使用时直接导人即可,例如可以导人预制的API RESPONSE PROMPT,它是引导模型根据API响应回答用户问题的提示词,导入方式如下:

from langchain.chains.api.prompt import API_RESPONSE_PROMPT

API RESPONSE PROMPT在源码中的定义如下:

API RESPONSE PROMPT TEMPLATE =
API URL PROMPT TEMPLATE
+""(api url}
Here is the response from the API:
(api response}
Summarize this response to answer the original question.
Summary:""
)
API RESPONSE PROMPT PromptTemplate
input_variables=["api_docs","question","api url","api response"],
template=API RESPONSE PROMPT TEMPLATE,
)

导入API RESPONSE PROMPT后,格式化外部输人变量,将提示词提交给模型平台的API:

from langchain.chains.api.prompt import API RESPONSE_PROMPT
prompt=API_RESPONSE_PROMPT.format(api_docs="",question="",
api_url="",api_response="")

构建复杂的提示词就像盖房子,LangChain的提示词模板做了"盖房子"的基建工程,比如内置的提示词模板不仅可以解决大多数的业务需求,还可以检查数据格式、规划提示词结构、格式化提示词等。这些基建工程通常用于描述模型的任务,或用于指示模型的行为。外部数据则是开发者自由添加的数据,这些数据可以来自各种渠道。最主要的外部数据有用户的输入、用户和模型的历史聊天记录,以及开发者为模型增加的外部知识库数据、程序运行的上下文管理信息。

例如,开发者可以收集并使用历史聊天记录,这些历史聊天记录可以帮助模型理解之前的对话上下文,从而生成更加连贯和有用的回答。开发者也可以使用用户的输人,这些输人被填充到模板占位字符串中,可以帮助模型理解用户的需求,从而生成更加符合用户期望的回答。此外,开发者还可以编写自己的示例文本,或者导人外部的文档片段,这些示例文本和文档片段可以帮助大语言模型理解任务需求,增加大语言模型的"脑容量"和"记忆时长",从而生成更加高质量的回答。

下图是一个典型的加人外部数据的提示词模板,它服务于RAG任务。RAG主要采用外部的知识库文档,将其插人提示词模板字符串中,让模型学习可能包含答案的上下文内容,模型学习了这些知识库文档后,生成答案的精确度将提升。2023年,AI创新领域常见的落地应用就是通过RAG提升机器人的回答质量。在LangChain框架中,通常用context代表检索到的相关文档内容,比如下图中的节点①{docs[i]},另外节点②是跟模型包装器交互过一次后生成的答案,也作为提示词的"中间答案",最终形成节点③的提示词。

在下图中,节点①和节点②注人提示词模板的数据即外部数据。更加复杂的RAG场景中还会加人历史聊天记录,聊天记录也是一种外部数据。总的来说,无论是内部数据还是外部数据,都是供提示词模板包装器生成更好提示词的,从而可以开发出更加强大的大语言模型应用。构造提示词的过程就是一项"提示词工程"。

提示词模板的输出,在LangChain中,提示词模板输出的是适用于各种模型平台API类型的提示词。例如,LLM类型API接收的输入是一个字符串,而Chat类型API接收的是一个消息列表。如果你使用GPT-4模型,那么你就需要准备一个消息列表提示词,而ChatPromptTemplate包装器输出的就是符合GPT-4模型要求的提示词。同模型包装器的分类一样,提示词模板包装器也分为PromptTemplate包装器和ChatPromptTemplate包装器两类。

PromptTemplate包装器可以输出一个字符串类型的提示词。这个字符串可能包含一些特定的任务描述、用户问题,或者其他的上下文信息,它们都被整合在一起,构成了一个完整的、用于引导模型生成预期输出的提示词。字符串类型提示词如下:You are a helpful assistant that translates English to FrenchChatPromptTemplate包装器可以生成一个消息列表格式的提示词。模型平台的Chat类型API通常需要一个消息列表作为输入,在这种情况下,这种包装器将构造出一个包含多个消息对象的提示词。每个消息对象都代表一条消息,它可能是一个用户问题、一个AI回答,或者一条系统指令。这些消息被组织在一起,形成了一个清晰的对话流程,用于引导模型完成复杂的对话任务。消息列表格式的提示词如下:

SystemMessage(
content=(
'You are a helpful assistant that translates English
'to French.'
),
additional kwargs={}
HumanMessage
content='I love programming.',
additional kwargs={}

无论使用哪种类型的API,只要选择对应的提示词模板包装器,就可以轻松生成符合API要求的提示词,这极大地简化了构造提示词的过程,使得开发者可以将更多的精力放在优化业务逻辑上,而无须手动处理复杂的数据转换和格式化工作。

使用提示词模板构造提示词

LangChain提供了一套内置的提示词模板,这些模板可以用来生成各种任务提示词。在一些基础和通用的场景中,使用内置模板可能就足够了,但在一些特定和复杂的场景中,可能需要创建自定义模板。这里介绍最常见的使用LangChain内置模板来构造提示词的方法。

PromptTemplate包装器,PromptTemplate是LangChain提示词组件中最核心的一个类,构造提示词的步骤本质上是实例化这个类的过程。这个类被实例化为对象,在LangChain的各个链组件中被调用。在实例化PromptTemplate类时,两个关键参数是template和input_variables。只需要准备好这两个参数就可以实例化一个基础的PromptTemplate类,生成结果就是一个PromptTemplate对象,即一个PromptTemplat包装器。

from langchain import PromptTemplate
template = """
You are an expert data scientist with an expertise in building deep learningmodels.
Explain the concept of (concept}in a couple of lines"""
#实例化PromptTemplate:
prompt = PromptTemplate(template=template,input variables=["concept"])
#实例化模板的第二种方式:
prompt PromptTemplate.from template(template)
#将用户的输人通过format方法嵌入提示词模板,并且做格式化处理
final_prompt prompt.format (concept="NLP")

打印final prompt提示词,结果如下:

'\nYou are an expert data scientist with an expertise in building deep learning
models.\nExplain the concept of NLP in a couple of lines\n'

创建提示词模板主要涉及两个要求:需要有一个input variables属性,这个属性指定了提示词模板期望的输人变量。这些输入变量生成提示词需要的数据,比如在以上示例中,输人变量就是{concept}。如果不想显式指定输入变量,还可以使用from template方法,见上述代码中的第二种方式。这个方法接收与预期的input variables对应的关键字参数,并返回格式化的提示词。在上面的示例中,from template方法实例化模板,format方法接收concept="NLP"作为输人,并返回格式化后的提示词。

PromptTemplate包装器可以被链组件调用,也可以调用其他方法(结合外部用户输人和内部定义的关键参数),最终的结果是实现内部数据和外部数据的整合,形成一个完整的提示词。

ChatPromptTemplate包装器,ChatPromptTemplate包装器与PromptTemplate包装器不同,ChatPromptTemplate包装器构造的提示词是消息列表,支持输出Message对象。LangChain提供了内置的聊天提示词模板(ChatPromptTemplate)和角色消息提示词模板。角色消,息提示词模板包括AIMessagePromptTemplate、SystemMessagePromptTemplate和HumanMessagePromptTemplate这3种。

无论看起来多么复杂,构造提示词的步骤都是通用的,将内置的模板类实例化为包装器对象,用包装器来格式化外部的用户输入,调用类方法输出提示词。下面我们将上一个示例改造为使用ChatPromptTemplate包装器构造提示词的示例。先导人内置的聊天提示词模板和角色消息提示词模板:

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

改造思路是生成人类消息和系统消息类型的提示词对象,将SystemMessage PromptTemplate类和HumanMessagePromptTemplate类实例化为包装器,再实例化 ChatPromptTemplate类,将前面两个对象作为参数传递给ChatPromptTemplate类实例化后的包装器,调用其from messages方法生成消息列表提示词包装器实例。

先使用from_template方法实例化SystemMessagePromptTemplate类和Human MessagePromptTemplate类,传人定义的template模板字符串,得到人类消息模板对象和系统消息模板对象:

from langchain import PromptTemplate
template ="""
You are an expert data scientist
with an expertise in building deep learning models."""
system_message_prompt =SystemMessagePromptTemplate.from_template(template)
human_template="Explain the concept of (concept}in a couple of lines"
human_message_prompt =HumanMessagePromptTemplate.from template (human template)

将上述两个模板对象作为参数传人from messages方法,转化为ChatPromptTemplate包装器:

chat prompt=ChatPromptTemplate.from messages
[system_message_prompt,
human_message prompt])

打印结果,如下:

ChatPromptTemplate(
	input variables=['concept'],
	output parser=None,
	partial_variables=(),
	messages=[
		SystemMessagePromptTemplate
		prompt=PromptTemplate
		input variables=[],
		output_parser=None,
		partial variables=(},
		template=(
			'\nYou are an expert data scientist with an expertise
			'in building deep learning models.\n'
),
	template format='f-string',
	validate template=True
	)
	additional kwargs={}
)
HumanMessagePromptTemplate(
	prompt=PromptTemplate
	input_variables=['concept'],
	output_parser=None,
	partial variables=(},
	template=(
		'Explain the concept of (concept}in a couple of lines'
),
	template format='f-string',
	validate_template=True
),
	additional kwargs=(}
])

最后使用包装器的format方法将用户输人传人包装器,组合为完整的提示词:

chat_prompt.format_prompt (concept="NLP")

调用format prompt方法,获得的是ChatPromptValue对象:

ChatPromptvalue(messages=[SystemMessage(content='\nYou are an expert data
	scientist with an expertise in building deep learning models.\n',
	additional kwargs=()),HumanMessage(content='Explain the concept of NLP
	in a couple of lines',additional_kwargs=(),example=False)])

ChatPrompt Value对象中有to string方法和to messages方法。调用to_messages方法:chat_prompt.format_prompt (concept="NLP").to_messages ()结果如下:

[SystemMessage(content='\nYou are an expert data scientist with an expertise
in building deep learning models.\n',additional_kwargs=()),
HumanMessage (content='Explain the concept of NLP in a couple of lines',
additional kwargs=(},example=False)]

调用to string方法,结果如下:

'System:\nYou are an expert data scientist with an expertise in building
deep learning models.\n\nHuman:Explain the concept of NLP in a couple of lines'

值得一提的是,PromptTemplate包装器和ChatPromptTemplate包装器在实现方式上存在差异,包括它们所使用的内置模板及实例化方法都有所不同。PromptTemplate包装器的内置模板是PromptTemplate类,而ChatPromptTemplate包装器的内置模板是ChatPromptTemplate类。PromptTemplate的实例化方法相对简单,只需要传递input variables和template参数后直接进行函数式调用或使用from template的类方法进行调用即可,比如:

PROMPT PromptTemplate.from_template (template=template)

相比之下,ChatPromptTemplate的实例化方法就复杂多了。它接收的参数是已经实例化的多个对象列表(如system_message_prompt和human_message_prompt)。如果把ChatPromptTemplate实例化的对象视为"大包",那么传人的包装器就是"小包",形成了一种"大包装小包"的情况。此外,这个"大包"的实例化类方法也与PromptTemplate不同,它使用的是from messages方法,这个方法只接收消息列表形式的参数,比如下面代码中的变量messages:.

messages=[
SystemMessagePromptTemplate.from_template(system_template),
HumanMessagePromptTemplate.from template ("(question)"),
CHAT PROMPT ChatPromptTemplate.from_messages(messages)]

尽管存在差异,但PromptTemplate包装器和ChatPromptTemplate包装器的实例化仍有一定的通用规律,这些规律方便记忆和使用。以format为前缀的类方法主要用于在实例化模板对象后将外部用户输人格式化并传入对象内。如果是实例化LLM模型包装器的内置模板对象,需要使用format方法,而实例化聊天模型包装器的内置模板对象则使用format prompt方法。

类似地,以from为前缀的类方法主要用于实例化内置模板对象。PromptTemplate类只能使用from template方法,而ChatPromptTemplate类则使用from_messages方法。此外,为了实现这两种类型的相互转换,聊天模型包装器使用format prompt方法实例化模板对象,生成的对象符合PromptValue数据模式。所有返回该数据模式的对象都包含以to为前缀的方法名,包括to_string方法和to_messages方法,分别用于导出字符串和包含角色的消息列表。

相关推荐
时雨h6 分钟前
Spring Bean 容器
java
知识鱼丸15 分钟前
自定义数据集 使用scikit-learn中svm的包实现svm分类
人工智能
说私域38 分钟前
基于开源AI智能名片2 + 1链动模式S2B2C商城小程序视角下的个人IP人设构建研究
人工智能·小程序·开源
山海青风1 小时前
OpenAI 实战进阶教程 - 第七节: 与数据库集成 - 生成 SQL 查询与优化
数据库·人工智能·python·sql
zimoyin1 小时前
Java/Kotlin HashMap 等集合引发 ConcurrentModificationException
java·kotlin
Chatopera 研发团队2 小时前
计算图 Compute Graph 和自动求导 Autograd | PyTorch 深度学习实战
人工智能·pytorch·深度学习
纠结哥_Shrek2 小时前
pytorch实现半监督学习
人工智能·pytorch·学习
白白糖2 小时前
深度学习 Pytorch 基础网络手动搭建与快速实现
人工智能·pytorch·深度学习
AI浩2 小时前
【Block总结】HWD,小波下采样,适用分类、分割、目标检测等任务|即插即用
人工智能·目标检测·分类
ZWZhangYu2 小时前
【实践案例】基于大语言模型的海龟汤游戏
人工智能·游戏·语言模型