介绍
如今,提示是与大型语言模型 (LLM) 交互的主要模式。提示需要根据用户需求进行调整,为 LLM 提供正确的上下文和指导 — 以最大限度地提高获得“正确”响应的机会。
这导致了提示工程 [1] 的兴起,并成为一门专业学科,提示工程师系统地进行试验,记录他们的发现,以得出“正确”的提示,从而引发“最佳”反应。然后,这些成功的提示列表以库的形式组织起来,以便可以有效地重复使用——称为提示存储库。
不幸的是,策划和维护高质量的提示库仍然具有挑战性。提示库的首要目标是能够检索给定任务的最佳提示,而无需重复整个实验过程。然而,这种检索说起来容易做起来难,主要是因为提示具有重叠性。
问题陈述
让我们尝试借助内容写作领域(当今 Gen AI 采用率最高的领域之一)的几个提示来理解重叠提示的问题:
提示 1:为宣布开设八十年代主题咖啡馆的博客文章撰写引人入胜的摘要。突出氛围和菜单。使用友好的语气来吸引老年顾客。
提示 2:为报纸上宣布开设现代主题咖啡馆的文章撰写不超过 200 字的引人入胜的摘要。突出装饰和菜单。使用友好的语气来吸引年轻的顾客群。
鉴于这两个提示都得到了(人工)审阅者的认可(甚至没有考虑基于 LLM-as-a-Judge 的技术),那么问题来了,应该将哪个提示添加到提示库中?至少有四个选项:
- 如果将两者添加进去,那么它们是不是太相似了,以至于在检索时很难区分?
- 添加其中一个,但这样我们就有可能丢失两个提示所特有的一些上下文,例如,这两个提示分别是报纸与博客文章、老年客户与年轻客户等;以及响应过滤器,例如,将响应限制为n 个单词 - 就像第二个提示的情况一样。
- 不添加任何内容,因为提示库中已经存在覆盖类似范围的提示。(同样的挑战也适用于LLM Cache的情况。)
- 添加一个模板,捕捉两个提示的通用特征,其中包含特定变量的占位符和这些变量允许的值列表(词汇表)。例如,涵盖上述提示的通用提示模板将如下所示:
为以下活动的帖子生成引人入胜的摘要。突出主题。使用指定的语气并将响应限制在字数以内。帖子(类型): [报纸、博客、文章……]活动: [咖啡馆、餐厅、小餐馆开业……]主题: [氛围、装饰、菜单……]语气: [友好、正式、信息丰富……]
这是推荐的方法,在下一节中,我们将展示像 LangChain 这样的框架如何使用提示模板来组织提示,以及它们支持的模板类型。
提示模板
LangChain提供了以下预定义的提示模板类[2]:
- PromptTemplate 是默认模板。
- ChatPromptTemplate 用于模拟聊天消息。
- FewShotPromptTemplate 应用小样本学习技术。
可以合并模板,例如合并 ChatPromptTemplate 与 FewShotPromptTemplate — 以适合用例。
让我们从基本的PromptTemplate 开始:
from langchain_core.prompts import PromptTemplate
prompt_template = PromptTemplate.from_template(
"Generate an engaging abstract for a {post} on the following {event}."
)
prompt_template.format(post="blog", event="opening of cafe")
它基本上适用于以带有变量(占位符)的字符串(句子)建模的提示,就像我们在上一节中考虑的示例提示一样。
如果您曾经使用过利用IBM Watson Assistant、AWS Lex、Google Dialogflow等技术的早期聊天机器人(ChatGPT 之前),那么这些概念可能与意图、话语和实体很相似。这种引导式聊天机器人需要通过首先提供一组提示、提示变体及其相应的响应来进行训练。提示可以分组为意图。提示变体(在聊天机器人术语中称为话语)是指不同用户可以提出相同提示的示例变体。最后,实体是指特定领域的词汇表,基本上是变量的允许值列表。
接下来,我们考虑ChatPromptTemplate,它允许对用户和 AI 系统之间的多步骤对话进行建模。可以指定用户、助手、系统等角色。允许的角色取决于底层 LLM 允许的角色。例如,OpenAI Chat Completions API允许指定以下角色:AI 助手、人类或系统。这些角色为对话提供了额外的背景信息,并有助于 LLM 更深入地理解对话。
from langchain_core.prompts import ChatPromptTemplate
chat_template = ChatPromptTemplate.from_messages(
[
("system", "You are a knoweldgeable AI bot. You are called {name}."),
("human", "Hi, how are you today?"),
("ai", "I'm doing great, thanks! How can I help you?"),
("human", "{user_input}"),
]
)
messages = chat_template.format_messages(name="Emily", user_input="How should I call you?")
最后,让我们考虑FewShotPromptTemplate类,该类允许通过在提出实际问题之前首先在样本问答词典上训练 LLM 来进行少量学习。
from langchain_core.prompts.few_shot import FewShotPromptTemplate
from langchain_core.prompts.prompt import PromptTemplate
examples = [
{"question": "What is the second largest ocean on Earth?", "answer": "Atlantc Ocean"},
{"question": "What is the tallest mountain in Asia?", "answer": "Mount Everest"},
]
example_prompt = PromptTemplate(
input_variables=["question", "answer"], template="Question: {question}\n{answer}"
)
prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
suffix="Question: {input}",
input_variables=["input"],
)
print(prompt.format(input="What is the tallest mountain in Africa?"))
基于强化学习的即时商店管理
LangChain 的提示模板是模板化和组织提示的绝佳解决方案。然而,当处理包含 100 多个提示(模板)的企业提示商店时,手动管理它们很快就会变得非常困难。对于每个新的(已批准和推荐的)提示,
- 提取提示模板和实体值。
- 确定与现有提示模板的重叠。
- 如果不存在覆盖的提示模板,则将该模板添加到提示存储中。
- 如果存在覆盖模板,但覆盖率低于(阈值)例如 70%,则可能需要根据缺失的实体和计数值调整模板。
即时商店策展流程如下图所示:
图:即时商店策展 流程(图片来自作者)
例如,给定以下(现有)提示模板
为以下活动的帖子生成引人入胜的摘要。突出主题。使用指定的语气。帖子(类型): [报纸、博客、文章……]活动: [咖啡馆、餐厅、小餐馆开业……]主题: [氛围、菜单]语气: [信息丰富、正式]
和新提示
为报纸上宣布开设现代主题咖啡馆的文章撰写不超过 200 字的引人入胜的摘要。突出装饰和菜单。使用友好的语气来吸引年轻的顾客群。
需要添加 (200) 字数限定符和以下实体值来适应现有的提示模板:主题
: [氛围、装饰、菜单]
语气: [友好、信息丰富、正式]
在后续文章中,我们概述了一种基于用户反馈的强化学习方法,以实现商店管理的自动化。
RL 模型的目的不是从头开始构建提示商店,而是利用用户反馈的提示来自动化提示商店的管理。
我们方法的核心是评分模型,该模型经过训练可根据用户反馈对提示-响应元组进行评分。该模型预测的分数用作 RL 代理的奖励。策略学习是离线进行的,这要归功于用户模拟器,该模拟器由提示存储中的提示模板实例化而成。策略学习是使用具有 epsilon-greedy 探索的深度 Q 网络 (DQN) 代理实现的,该代理经过量身定制,可有效包含超出范围的提示的后备响应。
强化学习模型
RL 模型架构如下图所示。
图:基于 RL 的提示商店管理架构(图片来自作者)
RL 模型的关键组件包括:NLU 单元,用于在热身阶段对 RL 代理进行初始训练;用户模拟器,从提示数据库中随机提取候选提示,以添加到新的用例、场景等中;根据用户对提示的反馈进行训练的分数模型,以及基于深度 Q 网络 (DQN) 的 RL 代理。
自然语言单元
自然语言理解 (NLU) 单元是一种意图识别 NLU,它使用提示库中现有的(和已批准的)提示模板进行训练。为简单起见,我们仅考虑了基本的 PromptTemplate(来自 LangChain),并使用来自Rasa 的开源 NLU ,使用TensorFlow管道。但是,RL 方法独立于所选的 NLU,可以轻松扩展到 NLU 引擎,例如 Google DialogFlow、IBM Watson 或 Amazon LEX。
用户反馈
我们在实际内部聊天机器人开发过程中获得了用户反馈,并将其运用到工作中。聊天机器人的作用是回答员工关于办公楼设施、人力资源政策和福利等方面的问题。
参与反馈过程的所有十位用户都被告知,他们的反馈将用于提高提示的质量。用户提供了对提示-响应三元组的二元反馈评级。因此,历史数据包含以下格式的四元组:(提示、响应、NLU 置信度和用户反馈)。
RL 奖励函数
评估 NLU 性能是计算语言学中一个长期存在的问题。从机器翻译 [4] 借用的评估指标在短句 [5] 上表现不佳,例如我们案例中的响应(模板)。另一方面,用户(人工)对提示响应的审核现在被认为是评估质量、准确性、扎实性等的事实标准——尽管这些分数通常很难收集且成本高昂。
为了以离线 RL 方式应用用户反馈,我们使用了一个能够为新的(未见过的)提示响应元组建模二元反馈的评分模型。句子的向量表示是使用通用句子编码器(可通过 TensorFlow Hub 获得)计算的。
鉴于此,分数模型学习在线性变换空间中投射提示和响应的向量表示,以便相似的向量表示给出高分。
为了训练 RL 奖励模型,我们利用 L2 正则化对平方误差(模型预测和人工反馈之间的误差)损失进行优化。为了评估模型,我们将预测分数转换为二进制结果,并与目标(用户反馈)进行比较。对于那些具有可识别模板且具有正反馈和接近 1 的 NLU 置信度的提示对,我们会执行数据增强,为提示和后备意图的组合分配低分数。
使用 DQN 进行 RL 代理策略学习
RL 代理使用具有 DQN 架构的 Q 学习算法来学习策略。我们遵循 [6] 提出的方法,使用完全连接的网络,由经验重放池缓冲区提供数据,其中包含提示和响应的独热表示以及相应的奖励。
在热身阶段,使用 NLU 置信度水平在 NLU 上训练 DQN。每当状态-动作元组的置信度值高于阈值时,DQN 训练集就会得到增强,方法是为给定状态和所有其他可用操作分配零权重。因此,在 RL 训练开始时,RL 代理的表现与 NLU 单元类似。
在 RL 训练期间,我们使用了 epsilon ε-greedy 探索,其中根据概率 ε 探索随机动作。我们使用随时间变化的 ε,这有助于在训练开始时进行探索,其中ε_t0 = 0.2,最后一个时期的ε_t = 0.05。
在一个时期内,我们模拟一批大小为n 个情节的对话(在我们的实验中范围为 10 — 30),并使用元组(s_t, a_t, r_t)填充经验重放缓冲区。缓冲区具有固定大小,当 RL 代理性能增加到指定阈值以上时,它会第一次刷新。在状态-动作元组获得大于 50% 的奖励的情节中,我们通过为当前状态的任何其他动作分配零奖励来执行数据增强。
结论
在本文中,我们重点讨论了构建企业提示商店的挑战。不幸的是,由于提示的重叠性质,策划和维护提示商店仍然是一项艰巨的任务。基本上,对于每个新的候选提示(要添加到提示商店),我们需要回答以下问题:
- 我们应该直接将其添加到提示商店吗?但这样提示商店的检索过程就会变得复杂。
- 我们如何解决提示存储中已存在的提示的重叠/冲突?在这些情况下,我们如何调整现有提示,以涵盖新候选提示的范围?
我们详细讨论了这个问题,重点介绍了一种以提示模板形式组织提示的结构化方法。我们给出了 LangChain 支持的提示模板类型的具体示例。最后,我们展示了如何使用强化学习和用户反馈实现提示商店策划流程的半自动化。
展望未来,需要更好的工具和策略来解决提示范围冲突,特别是在多领域提示商店的各自用户组(业务部门)对同一提示的实用性有不同看法的情况下。