摘要
检索增强式上下文学习已经成为一种强大的方法,利用冻结语言模型 (LM) 和检索模型 (RM) 来解决知识密集型任务。现有工作将这些模型结合在简单的“检索-读取”流程中,其中 RM 检索到的段落被插入到 LM 提示中。
为了充分发挥冻结 LM 和 RM 的潜力,我们提出了 DEMONSTRATE-SEARCH-PREDICT (DSP) 框架,该框架依赖于在 LM 和 RM 之间通过复杂的流程传递自然语言文本。DSP 可以表达高级程序,这些程序可以引导流程感知的演示、搜索相关段落并生成有根据的预测,系统地分解问题,使其成为 LM 和 RM 可以更可靠地处理的小型转换。
我们为开放域、多跳和对话场景下的问答任务编写了新的 DSP 程序,并在早期评估中取得了新的上下文学习最先进成果,分别比基线 LM (GPT-3.5)、标准检索-读取流程和同期自问流程取得了 37-120%、8-39% 和 80-290% 的相对提升。我们将在 https://github.com/stanfordnlp/dsp 发布 DSP。
1 引言
上下文学习通过在文本提示中包含任务指令和几个演示示例来调整冻结语言模型(LM),使其适应各种任务。对于问答、事实核查和信息寻求对话等知识密集型任务,检索模型(RM)越来越多地用于增强提示,从大型语料库中检索相关信息。
最近的研究表明,这种检索增强式上下文学习在简单的“检索-读取”流程中非常有效:将查询输入到 RM 中,并将检索到的段落作为提供 LM 响应上下文的一部分。在这项工作中,我们认为 LM 和 RM 都消耗(并生成或检索)自然语言文本,这为它们之间更复杂的交互提供了机会。充分实现这一点将具有变革性:冻结的 LM 和 RM 可以作为跨任务的通用基础设施,使机器学习和领域专家能够以更高的抽象级别快速构建有根据的 AI 系统,并降低部署开销和标注成本。
图 1 开始说明了检索增强式上下文学习的强大之处,但也突出了“检索-读取”方法的局限性。我们的查询是“大卫·格雷戈里继承的城堡有多少层?”。当被提示回答这个问题时,GPT-3.5(text-davinci-002;Ouyang 等人,2022 年)编造了一个虚构的城堡,其属性不正确,这突出了 LM 参数中存储的知识通常不可靠的常见现象(Shuster 等人,2021 年;Ishii 等人,2022 年)。引入 RM 组件有所帮助,因为 LM 可以将其响应建立在检索到的段落上,但冻结的检索-读取策略会失败,因为 RM 无法找到直接回答问题的段落。
图1所示。基于GPT3.5 (text-davinci-002)的三个系统的比较。LM本身经常做出错误的断言。当简单的搜索无法找到答案时,越来越流行的检索-读取管道就会失败。相比之下,任务感知DSP程序成功地分解了问题并产生了正确的响应。为演示而编辑的文本
我们引入了 DEMONSTRATE-SEARCH-PREDICT (DSP) 框架,用于上下文学习,该框架完全依赖于在冻结的检索模型 (RM) 和语言模型 (LM) 之间传递自然语言文本(和分数)。DSP 引入了一系列可组合的功能,用于引导训练示例 (DEMONSTRATE)、从知识语料库中收集信息 (SEARCH) 和生成有根据的输出 (PREDICT),从而系统地统一检索增强式 NLP 和上下文学习文献中的技术 (Lee 等人,2019 年;Khattab 等人,2021a;Anantha 等人,2020 年;Gao 等人,2022 年;Izacard 等人,2022 年;Dohan 等人,2022 年;Zelikman 等人,2022 年;Zhang 等人,2022 年)。
我们使用 DSP 来建议强大的知识密集型任务策略,这些策略由上述技术的组合构成。这揭示了上下文学习的一般性新概念可能性(第 2 节),并使我们能够展示丰富的程序,这些程序为上下文学习设置了新的最先进成果(第 3 节)。
图 1 展示了 DSP 程序可能采取的路径来得出答案,而图 2 则说明了如何通过精心设计的程序实现这一点。程序并没有直接要求 LM 回答这个复杂的问题,而是 SEARCH 阶段使用 LM 生成了一个查询:“大卫·格雷戈里继承了哪座城堡?” RM 检索到一条段落,说格雷戈里继承了 Kinnairdy Castle。在第二次搜索“跳转”找到城堡的层数后,PREDICT 阶段使用这些段落来查询 LM,以回答原始问题。
尽管这个程序实现了查询生成等行为,但它不需要手动标注这些中间转换的示例(即,检索跳转中生成的查询和段落)。相反,DEMONSTRATE 阶段使用标记的问答对来实现一种弱监督形式,该形式可以自动标注 SEARCH 和 PREDICT 中调用的转换。
图 2. 多跳问答 DSP 程序的一个示例。给定一个输入问题和 2-shot 训练集,DEMONSTRATE 阶段使用一种弱监督形式自动对训练示例中的中间转换进行注释。SEARCH 阶段从演示中学习,分解复杂的输入问题,并在两次检索跳转中检索支持信息。最后,PREDICT 阶段使用演示和检索到的段落来回答问题。
我们在开放域、多跳和对话场景下对多个 DSP 程序进行了问答评估。在这些程序中,我们实现了新颖且可重用的转换,例如使用弱监督对所有流程引导注释(第 2.3 节)、可靠地重写问题以解决对话依赖关系并使用中间跳转的摘要迭代分解复杂查询(第 2.4 节),以及使用自洽性从多个段落生成有根据的响应(第 2.5 节)。我们使用冻结的 LM GPT-3.5 和 RM ColBERTv2(Khattab & Zaharia,2020 年;Santhanam 等人,2022b 年)在 Open-SQuAD、HotPotQA 和 QReCC 上报告了初步结果,无需微调。我们的 DSP 程序分别比相应的基线 LM、标准检索-读取流程和同期自问流程(Press 等人,2022 年)取得了 37-120%、8-39% 和 80-290% 的相对提升。
本报告的后续版本将包括额外的测试任务和 LM 选择。
总之,本工作做出了以下贡献。首先,我们主张简单的、与任务无关的上下文学习流程应该让位于深思熟虑的、任务感知的策略。其次,我们展示了这种转变不必成为负担:使用 DSP,这样的策略可以轻松地表示为使用可组合运算符的简短程序。第三,这种组合性催生了强大的能力,例如能够自动标注复杂流程的演示,仅从最终任务的标签中。第四,对于三个知识密集型任务,我们实现了丰富的程序,为上下文学习建立了最先进的结果。
2 展示-搜索-预测
现在,我们引入了 DSP 框架,并通过提出一系列策略来展示其表达力,这些策略使 LM 和 RM 能够有效地共同解决复杂问题。我们在第 3 节展示了这些策略优于现有的上下文学习方法。我们首先讨论了 DSP 所基于的 LM 和 RM 基础模块(第 2.1 节),然后讨论了 DSP 内部的数据类型和控制流程(第 2.2 节)。随后,我们讨论了每个推理阶段:DEMONSTRATE(第 2.3 节)、SEARCH(第 2.4 节)和 PREDICT(第 2.5 节)。
2.1 预训练模块:LM和RM
一个DSP程序定义了语言模型LM和检索模型RM之间的通信。
语言模型我们调用一个冻结的语言模型 LM 来有条件地生成(或评分)文本。对于每次调用,程序都会准备一个提示,使 LM 适应一个特定的功能(例如,回答问题或生成查询)。一个提示通常包括指令、一些所需行为的演示,以及一个要回答的输入查询。
如图 2 所示,LM 不仅生成: (i) 对输入问题的最终答案(在 PREDICT 阶段),而且还生成 (ii) 中间的“跳转”查询,以找到对输入问题有用的信息(SEARCH)以及 (iii) 示例查询,展示如何为训练集中的问题生成查询(DEMONSTRATE)。这种对 LM 的系统使用是 DSP 程序的一个特点。
检索模型 DSP 程序还调用一个冻结的检索模型 RM,以检索对于给定查询最“相关”的 top-k 文本序列。RM 可以索引大量预定义的段落以实现可扩展的搜索,并且可以在不改变检索参数的情况下更新这些段落。RM 接受自由形式的文本输入,并专门用于估计文本序列与查询的相关性(或相似性)。
如图 2 所示,RM 负责检索(i)LM 生成的每个查询的段落(在 SEARCH 阶段),以及(ii)用于演示中的段落(DEMONSTRATE)。在后一种情况下,RM 的贡献较少在于直接为输入问题提供相关信息,而更多在于帮助 LM 适应领域和任务。
尽管在此示例中未使用,但 RM 在 DSP 中还用于诸如从任务训练数据检索“最近邻”演示(DEMONSTRATE)和从 LM 选择基于事实生成的序列(PREDICT)等功能。
2.2 数据类型和控制流
我们使用 Python 实现了 DSP 框架。本节介绍了框架提供的基本数据类型和可组合函数。我们使用示例代码片段来说明这些例子,并传达了能够在简单程序中表达 LM 和 RM 之间复杂交互的力量。
示例数据类型为了执行任务,DSP 程序操作一个或多个 Example 数据类型的实例。一个 Example 类似于具有多个字段的 Python 字典。程序通常会被提供几个训练示例。下面的代码片段展示了这对于多跳问答的情况。
这段代码包含两个标记的示例,每个示例都有一个多跳问题(例如,“Akeem Ellis 在 2017 年在哪个城市打球?”)及其简短答案(“Ellesmere Port”)。在 Example 中允许任意键和值,尽管典型的值是字符串或字符串列表。
在此任务中,我们不太可能找到一个单独的段落能提供任何问题的答案。例如,第一个训练示例可能只能通过首先回答谁发现了帕洛马(“埃德温·哈勃”)的问题,然后使用不同的证据段落来解答哈勃的出生日期问题。我们通常假设人类标记的训练数据不包括对中间转换(例如,单个跳转的查询)的标签,这些转换对于执行这些步骤会有用,因此 DSP 程序的任务是通过上下文学习发现这些策略。
DSP 程序以下代码片段是一个完整的程序,用于解决类似于图 1 中的多跳问题,并得到上述训练示例的帮助。
程序接受输入(此处为一个问题)并输出系统输出(其简短答案)。它首先为输入问题创建一个 Example,并将训练字段分配给之前的代码片段中的训练集。程序调用和组合 DSP 基本操作(即内置函数)来构建定义程序的 DEMONSTRATE、SEARCH 和 PREDICT 转换。
转换 转换是一个函数,它接受一个 Example 作为输入并返回一个 Example,在其中填充新的字段(或修改现有字段)。这个程序调用了三个由开发者定义的转换,即multihop_demonstrate、multihop_search 和 multihop_predict。转换本身也可以调用其他转换,它们与标准深度神经网络(DNN)编程框架(如 PyTorch)中的层类似,不同的是它们在彼此之间传递文本数据而不是张量,并不涉及反向传播。
我们将转换根据它们在 DEMONSTRATE、SEARCH 和 PREDICT 阶段的行为(或目的)进行分类。尽管如此,DSP 并不强制执行这种分类,允许我们定义可能融合这些阶段的函数。我们将在下一节讨论这三个阶段。
2.3 展示
已知在 LM 的提示中包含所需行为的示例通常会导致更好的性能(Brown 等人,2020 年)。在 DSP 中,演示是一个经过准备的训练示例,用于展示 LM 的特定所需行为。DEMONSTRATE 转换接受类型为 Example 的输入 x,并为 x.demos 准备一个演示列表,通常通过从 x.train 中的训练示例中选择子集并引导新的字段来实现。
引导演示 训练集中的示例通常包含任务的输入文本和目标输出。DEMONSTRATE 阶段可以通过编程方式引导注释来增强训练示例。在我们的“多跳”示例中,演示展示了三个基于 LM 的转换:
(i)如何分解输入问题以收集回答它的信息(即第一跳检索),
(ii)如何使用之前“跳”中收集的信息来提出后续问题,
(iii)如何使用收集到的信息来回答复杂问题。
类似于一个专业的地图,annotate 原始函数接受一个用户定义的转换函数 fn 并将其应用于一个训练示例列表。每当 fn 返回一个示例(而不是 None)时,annotate 会缓存中间预测(即生成的查询和检索到的段落)。这些预测作为管道转换的成功演示。在简单使用中,fn 可能尝试一次或多次回答示例的“零样本”问题。这通常是通过调用程序的 SEARCH 和 PREDICT 阶段来实现的。当产生一个答案时,如果 fn 认为它是正确的,它会返回一个填充好的示例,其中包含中间预测。
案例学习 下面的代码片段定义了multihop_demo函数(在multihop_program的第3行中调用),并演示了annotate的用法。
在第 10 行,multihop_demonstrate 调用了 annotate,它通过缓存 attempt_example 的注释来引导训练示例中缺失的字段。转换 attempt_example 接收一个训练示例 d 并尝试以零样本的方式回答它:它创建了一个 d 的副本,其中没有演示(第 4 行;即零样本)并调用多跳搜索和预测管道(第 5 和 6 行)。每个转换都会返回一个带有额外字段填充的 d 的更新版本。如果管道回答正确(第 7 行),则返回更新后的 d。
图 2 展示了这种行为。DEMONSTRATE 转换一个训练问题-答案对到一个完全填充的演示中,包括 hop1 和 hop2(即多跳搜索的查询)以及 psg1 和 psg2 字段。当 LM 后来被调用以执行某个转换,例如在 SEARCH 阶段生成一个“第二次跳转”查询时,psg1 字段作为上下文,而 hop2 字段则作为这个特定训练示例的标签。
讨论 这个简单的案例研究展示了 DSP 抽象中组合的力量。因为管道是一个定义良好的程序,其中转换通过附加在示例上的文本进行通信,一个简单的映射和过滤策略可以利用 LM 和 RM 从最终任务的标签来引导注释整个管道。这是一个可扩展的策略,但即使在它的最简单形式中,它也推广了 Zelikman 等人(2022 年)、Wei 等人(2022 年)、Zhang 等人(2022 年)和 Huang 等人(2022 年)最近探索的方法,在这些方法中,LM 为单个提示自我生成思维链的理性。
通过引导管道,DEMONSTRATE 使得在 SEARCH 和 PREDICT 中探索复杂策略变得容易,而不必为每个转换编写示例。这包括在传统检索增强 NLP 中难以探索的策略,因为需要自定义注释。例如,Khattab 等人(2021a)介绍了一个用于多跳推理的管道,它使用弱监督进行训练,扩展了 Lee 等人(2019 年)和 Khattab 等人(2021b)的工作。在其中,需要检索的目标 3 或 4 个段落必须被标记,但系统自动发现最佳的“跳转”顺序。
相比之下,DSP 允许我们构建复杂管道,而无需中间步骤的标签,因为我们能够将小转换组合成程序。如果 LM 和 RM 能够“零样本”(即无需演示)准确处理这些转换,至少在一个或两个示例上,这些示例可以使用最终任务的标签发现并用作演示。
用我们之前与 PyTorch 等深度神经网络框架的类比来说,DEMONSTRATE 旨在以可扩展的方式替换反向传播的功能,通过模拟程序的行为(对应于“前向”传递)并从错误中程序化学习。这样做时,DEMONSTRATE 在冻结模型和仅使用最终任务标签的情况下引入了高度的模块性。特别是,无需手动标注中间转换,开发者可以更换训练领域、更新训练示例或修改程序的策略,并使用 annotate 来自动填充演示的所有中间字段。
选择演示 示例并非总是可以将所有训练示例放入 LM 的上下文窗口中。DSP 提供三个用于选择训练示例子集的原语,即 sample、knn 和 crossval。
作为基线选择,可以使用 sample 原始函数随机从 train 中抽取 k 个演示示例,这是 Brown 等人(2020 年)以及后续许多工作的做法。我们还可以利用 RM 的表示,从训练集中选择与输入文本最接近的 k 个最近邻,这是 Liu 等人(2021 年)探索的策略。另一种策略是对多个抽样示例集应用交叉验证,以选择表现最佳的示例集(Perez 等人,2021 年)。例如,给定 jtrainj = 100 个训练示例,crossval 会选择 n 个包含 k = 5 个示例的子集,并返回与剩余 95 个示例上转换evaluate 表现最佳的子集。
组合与扩展 通过操纵演示和更高阶的转换,这些简单的选择和引导原始函数可以组合成更大的新策略。如果训练集非常大(例如,jtrainj = 100; 000),我们可以使用 knn 找到最接近的 k = 16 个示例,并只对这些示例进行注释,从而实现一个实时增量学习的系统。如果训练集适中(例如,jtrainj = 1000),我们可以进行交叉验证,并在每个训练示例上缓存它评估的所有提示的性能。在测试时,我们可以使用 knn 找到与测试输入最相似的 k = 50 个示例,并选择在这些 k 个示例上表现最佳的提示,产生一个适应性系统,该系统根据其管道在不同类型示例上的质量进行调整。
2.4 搜索
SEARCH 阶段收集段落来支持由 LM 执行的转换。我们假设有一个大型知识语料库——例如,网页、维基百科或 arXiv 的片段——被划分为文本段落。向 LM 提供段落有助于提供事实性响应,允许在不重新训练的情况下更新知识库,并提出了一个透明度契约:当有疑问时,用户可以检查系统是否忠实地使用了一个可靠来源来做出预测。
在最简单的场景中,SEARCH 可以直接查询 RM,请求与输入问题匹配的前 k 个段落(来自预定义的索引)。这种 SEARCH 的基本实现模拟了大多数开放域问答系统中检索的实现,它们实现了一个“检索-然后-阅读”的流水线,如 Lee 等人(2019 年)、Khattab 等人(2021b 年)、Lazaridou 等人(2022 年)以及许多其他人。
SEARCH 策略 在许多场景中,任务的复杂性要求更复杂的 SEARCH 策略,以使检索模型(RM)能够找到相关的段落。我们正在运行的示例(图 2)就是这样一个场景,我们怀疑示例很可能需要特定的多跳推理。其他设置,例如,提出对话挑战,在这种情况下,用户表达的信息需求只能通过考虑对话中的前几轮来解决,或者需要更广泛的规划(Zhong 等人,2022 年)。
在检索增强 NLP 的文献中,多跳搜索(Xiong 等人,2020 年;Khattab 等人,2021a 年)和对话搜索(Del Tredici 等人,2021 年;Raposo 等人,2022 年)流水线受到了广泛关注。这些系统通常需要经过许多手工标记的查询“重写”(Anantha 等人,2020 年)、“分解”(Geva 等人,2021 年;Min 等人,2019 年)或目标跳转(Yang 等人,2018 年;Jiang 等人,2020 年)的微调。在 DEMONSTRATE 提供的自动注释的支持下,SEARCH 阶段允许我们模拟许多这样的策略以及许多其他策略,这些策略涉及到在 RM 和 LM 之间传递查询、段落和演示。更重要的是,SEARCH 促进了我们对于高级策略的愿景,即 LM 和 RM 合作逐步规划研究路径,其中 RM 收集信息,而 LM 确定下一步。
案例研究 让我们在我们的多跳示例基础上进行更深入的研究。我们可以定义 multihop_search_v2(在我们的核心程序中的第 4 行),这是图 2 中 SEARCH 转换的一个略微更高级的版本。这个转换模拟了像 IRRR(Qi 等人,2020 年)这样的微调检索增强系统的迭代检索组件,后者在每次跳转时阅读检索到的段落并生成一个搜索查询(或一个停止跳转的条件),以及像 Baleen(Khattab 等人,2021a 年)这样的系统,后者在每次跳转时总结许多段落的信息,以包括在后续跳转中。
在 multihop_search_v2 中,第 7 行调用了 generate 原始函数,该函数调用了 LM 生成每个检索跳转的查询。LM 基于一个使用 hop_template 模板准备的提示进行条件化。(我们将在第 2.5 节讨论提示模板和 generate 原始函数。)在这里,这个模板可能被设计为生成一个具有以下格式的提示(例如,对于第二次跳转)。
如图所示,LM 被指示阅读早期跳转中检索到的上下文和一个复杂的问题。然后它被提示编写:(i)提供的上下文的摘要;(ii)一个搜索查询,用于收集回答那个问题的信息。生成的文本将被提取并分配给 multihop_search_v2 中的 summary 和 query 变量(第 7 行)。在第 10 行,如果查询是“N/A”,则终止跳转。否则,在第 12 行,使用查询检索 k = 5 个段落,并在第 13 行将后续跳转(或 PREDICT)的上下文分配给变量,该变量包括所有先前跳转的摘要以及到目前为止检索到的最终跳转中的段落。
与自问技术的比较 这可能很有启发性,我们将这种多跳 DSP 程序与最近的“自问”(Press 等人,2022 年)提示技术进行对比,这在第 3 节中进行了比较。自问可以被看作是 DSP 的 SEARCH 阶段的简单实例。在其中,LM 提出一个或多个“后续问题”,这些问题被拦截并发送到搜索引擎。搜索引擎的答案被连接到提示中,并用于回答问题。这本质上是对 IRRR(Qi 等人,2020 年)的简化模拟。
作为一般框架,DSP 可以表达自问等想法,以及我们在本节中讨论的许多其他更复杂的管道。更重要的是,DSP 提供了一系列固有优势,这些优势导致显著的实证收益:比自问高出 80%–290%。例如,DSP 程序具有深刻的模块性,这意味着 DSP 程序将注释并构建自己的演示。因此,它们可以在不标注任何中间转换(例如,生成的查询)的情况下开发。此外,DSP 构建的 LM 提示会自动更新,以与提供的训练数据和检索语料库保持一致。相比之下,像自问这样的方法依赖于手工编写且硬编码示例的提示。
此外,DSP 将控制流分配给一个显式的程序,并促进了调用 LM(或 RM)进行小转换的设计模式。这使我们能够构建专门用于生成一个或多个检索查询、每个跳转总结多个段落和回答问题的步骤。这些步骤比自问提示的步骤更简单,但我们的多跳 DSP 程序故意组合它们来构建更丰富的管道,因此更加可靠。相比之下,自问将控制流委派给 LM 完成,在提示本身内保持状态并拦截后续问题以执行搜索。我们发现这种范式导致了“自我分散”问题(第 3.5 节),而 DSP 程序可以避免。
融合检索结果 为了提高召回率和健壮性,我们还可以融合多个生成查询的检索结果。融合在信息检索领域有悠久的历史(Fox & Shaw, 1994; Xue & Croft, 2013; Kurland & Culpepper, 2018),并且最近 Gao 等人(2022 年)探索了使用多个查询按顺序处理以追溯归因于 LM 生成的文本。受这些工作的启发,我们在 DSP 中包含了一个 fused_retrieval 原始函数,以提供一个与冻结检索器交互的通用机制。它接受一个可选的融合函数,该函数将多个检索列表映射为一个。默认情况下,DSP 使用 CombSUM(Fox & Shaw, 1994)的一个变体,为每个段落分配其在检索列表中的概率之和。
为了说明这一点,下面的修改为转换multihop_search_v2生成n = 10个查询。
组合与扩展 为了说明一个简单的组合,我们可以通过将一个查询重写步骤与多跳转换结合起来,为聊天机器人装备进行对话多跳搜索的能力,如下所示。
类似的方法也可以用于纠正拼写错误或实现伪相关反馈(Cao 等人,2008 年;Wang 等人,2022a 年),其中检索到的段落用于告知一个更好的搜索查询,尽管据我们所知,这还没有尝试过与预训练的 LM 结合使用。
2.5 预测
PREDICT 阶段使用演示(例如,在 x.demos)和段落(例如,在 x.context)来生成系统输出。PREDICT 挑战可靠地解决下游任务,这整合了上下文学习领域的许多工作。在 DSP 中,它还具有更专业的功能,即系统地汇总大量演示、段落和候选预测的信息。
生成候选项 通常,PREDICT 需要为最终任务生成一个或多个候选预测。为此,PREDICT 的基本原始函数是 generate,它接受一个模板和一个示例,并通过封装(currying)查询 LM 以产生一个或多个完成项,如第 2.4 节中之前所探索的。与此阶段使用 RM 相对应的原始函数是 rank,它接受一个查询和多个段落,并返回它们的关联性评分。
模板是一个可以产生提示的对象,也就是说,将一个示例映射到一个字符串,并从补全中提取字段。例如,我们可以将包含问题和检索段落的示例x映射到以下提示符:
如上图所示,LM将被要求生成思想链原理(CoT;Wei et al . 2022;小岛等人2022)和答案,生成的文本将被提取回每个完成的基本原理和答案键。
对LM的每次调用都可以对多个候选预测进行采样。选择“最佳”预测是解码工作的主题(Wiher等人,2022;Li et al, 2022),但冻结的通用LM可能不支持自定义解码修改。在这些限制条件下,我们提出了几种高级策略,用于通过LM和RM在DSP中选择预测和聚合信息。
在多个候选项中,我们可以简单地提取最受欢迎的预测。当使用 CoT 到达答案时,这就是 Wang 等人(2022c)的自一致性方法,它寻求识别多个不同的推理到达的预测。
DSP 在两个方面推广了这一点。首先,我们可以在整个程序中采样多个“转换管道”(PoT),而不是在一个转换中本地使用“思维链”(CoT)。这些链甚至可以调用程序中的不同路径,如下所示。
在上面的代码片段中,第 10 行调用了 branch 原始函数,该函数以高温度(例如,t = 0:7)采样 n 个不同的 PoT,并积累它们的中间和最终预测。在这个例子中,我们的管道调用了 multihop_search_v2(第 2.4 节),它根据生成的问题应用一个可变的检索跳数,然后再进行 PREDICT。也就是说,PoT_program 可能会在分支中调用程序中的多个不同路径(即每个路径具有不同的多跳查询和跳数)。然后它选择多数答案。
DSP 以另一种方式推广了自一致性。当我们采样我们的 CoTs 或 PoTs 提供多个候选项时,我们可以选择前 k 个(例如,前 4 个)预测,然后直接比较它们。例如,我们可以提示 LM 比较这些选择作为多项选择题(MCQ)的候选项,这是一个 DEMONSTRATE 可以自动准备的转换。这实际上模拟了 Levine 等人(2022 年)的 LM 递归,尽管与他们的方法不同,它不需要大量训练数据或更新任何(提示调优)权重。一个这样的实现可以在下面的 openqa_predict 中看到。
作为另一种比较方法,我们可以通过 rank 调用 RM 来找到最基于检索上下文的预测(即与检索到的段落的串联最相似),或者,如果 RM 能够为完成项评分(Krishna 等人,2022 年),那么可以直接选择给定提示下评分最高的预测。
汇总信息当只选择少数演示或段落时,我们可以简单地将它们全部连接到提示中。例如,GPT-3.5 text-davinci-002 有一个 4097 个令牌的上下文窗口,我们发现这个窗口对于容纳几个(例如,3-5 个)演示来说相当大,每个演示都包含自己的段落和推理。
处理更多演示或段落时,我们可以并行分支来处理单个子集的段落或演示,然后使用前面介绍的评分方法之一汇总单个答案。事实上,Lewis 等人(2020 年)和 Lazaridou 等人(2022 年)探索了边缘化作为跨段落组合得分的方法,Le 等人(2022 年)则将提示跨演示进行集成,这可以用这种方式表达。
另一种汇总策略是依次在段落之间累积信息,而不是独立地。这就是我们的多跳方法(第 2.4 节)实际工作的方式。这种策略也被 Gao 等人(2022 年)最近用于追溯归因于 LM 生成的文本到引证。他们生成许多查询,但不是融合(第 2.4 节),而是对每个查询运行其管道,并使用其输出来修改后续查询的输入。
3 评估
我们现在考虑如何为三个不同的知识密集型 NLP 任务实现 DSP 程序:开放域问答(QA)、多跳问答和对话问答。所有这些任务都是“开放域”的,这意味着系统被给予一个简短的问题或参与多轮对话,而没有被授予访问回答这些问题的上下文。
我们为每个任务构建并评估了在第 2 节中探索的函数的直观组合。我们展示出,尽管开发努力较低,但生成的 DSP 程序展现出强大的质量,并且在上下文学习中超过了基线和带有上下文学习的标准检索-阅读流水线。
3.1 评估方法
在本报告中,我们为每个考虑的任务考虑了一个开发数据集,即开放域版本的 SQuAD(Rajpurkar 等人,2016 年;Lee 等人,2019 年)、多跳 HotPotQA(Yang 等人,2018 年)数据集在开放域“fullwiki”设置中,以及用于开发 DSP 抽象的对话问答 QReCC(Anantha 等人,2020 年;Vakulenko 等人,2022 年)数据集。我们在所有三个数据集上报告验证集的准确率,并在第 3.5 节中详细讨论。
除非另有说明,系统可以访问 16-shot 训练示例,即每个 DSP 程序可以使用(最多)16 个问题——或者对话,如果适用——从各自的训练集中随机抽取。我们将验证集和测试集下采样到 1000 个问题(或者在适用的情况下 400 个对话),并在五个种子中报告平均质量,每个种子固定一个单一的 k-shot 训练集示例。为了控制语言模型 API 的支出预算,每个种子处理评估示例的五分之一(例如,每个种子 200 个问题,总共 1000 个唯一问题)。
我们还预留了测试数据集(例如,OpenNaturalQuestions;Kwiatkowski 等人,2019 年)和测试任务(例如,FEVER 中的主张验证;Thorne 等人,2018 年),我们只用这些数据集和任务来评估预定义的 DSP 程序,而不是用于开发。我们将在报告的下一个版本中包括这些结果。
3.2 预训练模块
RM 我们使用 ColBERTv2(Santhanam 等人,2022b),这是一个基于晚期交互的先进检索器(Khattab & Zaharia,2020 年)。我们选择 ColBERTv2 是因为它的零样本搜索质量和高效的搜索(Santhanam 等人,2022a)。然而,我们的 DSP 程序对于检索器如何表示示例或评分段落是无关紧要的,所以基本上可以使用任何检索器。
此外,通过将检索作为一个一等构造,DSP 允许我们随着时间的推移改变或更新搜索索引。我们在实验中通过将每个数据集与 Chen 等人(2017 年)的 2016 年 12 月维基百科数据、Yang 等人(2018 年)的 2017 年 11 月维基百科“摘要”数据以及 Karpukhin 等人(2020 年)的 2018 年 12 月维基百科数据进行对齐来模拟这一点。
LM 我们使用 GPT-3.5(text-davinci-002;Brown 等人,2020 年;Ouyang 等人,2022 年)语言模型。除非另有说明,我们在生成 n = 1 的预测时使用贪婪解码。当 n > 1 时,我们使用温度 t = 0:7 进行采样,就像相关工作(Wang 等人,2022c 年)一样。
3.3 基线
基线 LM 这些基线代表了 Brown 等人(2020 年)使用的少量示例上下文学习范式。开放域 QA 和多跳 QA 的基线从训练集中随机采样 16 个演示(即每个程序在评估中可用的所有示例),并不对这些演示进行增强。同样,对话 QA 的基线也采样了四个对话。基线 LM 不会搜索与输入查询相关的段落。
检索-阅读 “检索-阅读”基线使用 RM 在提交提示给 LM 之前,为每个示例提供可能相关的段落支持。这模仿了用于最新开放域问答系统的流水线(Khattab 等人,2021b;Izacard & Grave,2020;Hofstätter 等人,2022)。在对话 QA 中,我们将第一轮和最终问题连接起来,我们发现这种方法比简单地使用最终问题要好得多。对于多跳 QA,我们为每个问题检索并连接两个段落。
自问 我们也与自问(Press 等人,2022 年)进行了比较,这是一种同时期的流水线,可以被视为 DSP 的 SEARCH 阶段的特定实例,后面跟着一个简单的 PREDICT 步骤。为了与我们的方法直接比较,我们修改了自问的控制流,使其查询我们 DSP 实验中使用的相同 ColBERTv2 索引,而不是 Google 搜索。我们评估了两种自问配置。第一种使用原始自问提示模板,其中包含四个手工写的演示。在第二种配置中,我们修改了提示模板,应用了我们发现对 HotPotQA 有用的几个变化。
3.4 提出的 DSP 程序
我们基于第 2 节中提出的转换。我们为所有三个任务构建的程序具有以下结构,以开放域 QA 为例进行说明。
例外的是,对话 QA 程序 convqa_program 接受轮次(即一系列字符串,代表对话历史),而不是单个问题。除非另有说明,我们的程序在 DEMONSTRATE 阶段默认使用贪婪解码。
对于 SEARCH,我们的开放域 QA 程序直接使用问题来检索 k = 7 个段落,并将这些段落与 CoT 连接到我们的 QA 提示中。对于 PREDICT,它生成 n = 20 个推理链,并使用自一致性(SC;Wang 等人,2022c)来选择其最终预测。对于 DEMONSTRATE,我们的开放域 QA 程序使用以下方法,为了演示而略有简化。在这个方法中,向 annotate 请求传递的参数 k = 3,只注释三个演示,这些演示将然后用于提示中。
我们的多跳程序在 DEMONSTRATE 和 PREDICT 方面采用了非常相似的方法。对于 SEARCH,它使用了第 2.4 节中描述的方法,并进行以下调整。它使用跨 n = 10 个查询每跳的结果融合,并在 n 个预测中使用对应于最大平均对数概率的摘要。对于 HotPotQA,它使用固定的跳数,即两跳。在每个提示(即每个跳和 QA)中,它将所有前跳(即从 hop 1 开始)的摘要连接起来,并总共使用 k = 5 个段落,这些段落分布在跳之间(即从第一个跳使用五个段落或从第一个跳使用两个段落,从第二个跳使用三个段落)。
对于对话 QA,我们使用一个简单的 PREDICT,它使用贪婪解码生成一个响应,该响应取决于所有先前对话的轮次和五个检索到的段落。对于 SEARCH,我们的对话 QA 流水线生成 n = 10 个重写的查询(并也使用简单的查询作为检索和阅读基线;第 3.3 节),并将它们融合,就像在第 2.4 节中描述的那样。我们实现 DEMONSTRATE 与 openqa_demonstrate 类似,但只采样四个示例(即四个对话轮次;而不是开放域 QA 中的 16 个问题)来演示任务,以用于更高阶的转换 convqa_attempt,该转换传递给 annotate(由于简洁,未在此处展示)。
3.5 开发的数据集和结果
Open-SQuAD 我们在 Chen 等人(2017 年)处理的维基百科 2016 语料库上进行开放域版本的 SQuAD,如 Khattab 等人(2021b 年)所处理。我们使用与 Karpukhin 等人(2020 年)和 Khattab 等人(2021b 年)相同的训练/验证/测试划分。
表 1 报告了答案的 EM 和 F1。任务感知的 DSP 程序实现了 36.6% 的 EM,比基线 LM 提高了 126% 的 EM 相对收益。这表明将 LM 的预测建立在检索上非常重要,并且表明像 ColBERTv2 这样的最新检索器具有实现这一目标的能力。提出的 DSP 程序在 EM 中相对收益提高了 8%,在 F1 中相对收益提高了 6%,超过了检索-然后-阅读流水线,这突出了通过我们使用自一致性方式聚合多个检索到的段落信息可以获得非平凡的收益。
表 1. 开发结果比较,包括一个任务感知的 DSP 程序与基线 LM、检索-然后-阅读 LM 以及近期和同时代的上下文学习方法(带检索和不带检索)。我们所有的运行都使用了 GPT-3.5,检索基础的行使用了 ColBERTv2。标记为 { } 的结果收集自截至 2022 年 12 月中旬的相关工作,并在正文中归因于各自的来源。正如我们在正文中所讨论的,标记的结果通常不是直接的比较,因为它们跨越了各种评估设置。尽管如此,我们在这里报告它们作为定性参考点。
这些上下文学习结果与许多流行的微调系统相竞争。例如,在 Open-SQuAD 测试集上,DPR 实现了 29.8% 的 EM,远低于我们的 16-shot DSP 程序。在 Open-SQuAD 开发集上,当调用五个检索到的段落时,强大的 Fusion-in-Decoder(Izacard & Grave,2020)“基础”方法实现了大约 36%(即与我们的系统质量非常相似)。尽管如此,他们的系统在默认设置下阅读 100 个段落时,在这个评估中达到了 48% 的 EM。这可能表明,如果 PREDICT 阶段被调整为聚合更多信息,我们的 DSP 程序也可能实现类似的收益。
为了比较,我们还评估了自问流水线,其实现了 9.3% 的 EM,这表明其固定的流水线在其默认的多跳设置之外是无效的。研究其几个错误示例揭示了它经常以不相关的方式分解问题并回答这些问题。我们将 LM 的这种行为称为“自我分散”,并认为这增加了对我们 DSP 中设计决策的支持。为了说明自我分散,当自问被提示“The Kidnapping of Edgardo Mortara 何时发生?”时,它问道“The Kidnapping of Edgardo Mortara 是什么?”然后问它何时出版,这是一个不相关的问题。因此,自问回答“1997”,而不是 The Kidnapping of Edgardo Mortara 发生的时间(1858)。
作为参考,表 1 还报告了 Si 等人(2022 年)使用 code-davinci-002 的同时上下文学习结果(No-retrieval LM SoTA),他们在不检索的情况下实现了 20.2% 的 EM,在检索的情况下实现了 34.0% 的 EM,尽管是在 SQuAD 数据的另一个样本和划分上。总体而言,他们的方法与我们实现的基线(基线 LM 和检索-然后-阅读)非常相似,尽管他们的检索增强方法检索(并将 10 个段落拼接到提示中)了维基百科的数据。
HotPotQA 我们使用 HotPotQA 的开放域“fullwiki”设置,使用其官方的 2017 年“摘要”语料库。HotPotQA 测试集是隐藏的,所以我们保留官方的验证集用于我们的测试。我们将训练集划分为 90%/10% 的训练/验证划分。在训练(以及因此的验证)划分中,我们只保留原始数据集中标记为“hard”的示例,这与官方验证和测试集的指定相匹配。
我们在表 1 中报告了最终答案的 EM 和 F1。在 HotPotQA 上,任务感知的 DSP 程序在所有基线和现有工作中表现最佳,EM 分别比基线 LM、检索-然后-阅读基线和自问流水线高出 82%、39% 和 80%。这突出了构建更复杂的程序以协调 LM 和 RM 的 SEARCH 步骤的有效性。
这些结果可以与同期论文中对 HotPotQA 的评估进行比较。我们首先与非检索方法进行比较,尽管我们的比较必须保持谨慎,因为评估方法存在差异。Si 等人(2022 年)使用 CoT 提示实现了 25.2% 的 EM。使用 PaLM-62B 的“背诵-然后-回答”技术,Sun 等人(2022 年)实现了26.5% 的 EM。当为 PaLM-540B 应用自一致性提示时,Wang 等人(2022b 年)实现了 33.8% 的 EM 和 44.6 F1。接下来,我们与同时代的基于检索的方法进行比较:Yao 等人(2022 年)使用能够使用 Wikipedia API 进行搜索的系统实现了 35.1% 的 EM。所有这些方法都远远落后于我们的任务感知的 DSP 程序,该程序实现了 51.4% 的 EM。
QReCC 我们在 Wikipedia 2018 的开放域设置中使用 QReCC(Anantha 等人,2020 年)。QReCC 没有官方的开发集,所以我们从训练集中划分为 90%/10% 的训练/验证划分。对于每个对话中的第一个问题,我们使用重写的查询作为原始查询,因为原始查询通常假设访问了真实文档。我们还从 QReCC 中过滤低质量的示例。
我们以自回归方式进行 QReCC 对话。对于特定对话的第 t > 1 轮,系统看到它对之前对话轮次的响应(即不是真实响应)。我们报告新颖-F1 指标(nF1;Paranjape 等人,2022 年),该指标计算系统响应与真实响应之间的 F1 重叠,同时折扣常见停用词和问题(或之前的问题)中出现的术语。结果在表 1 中显示,并遵循与 SQuAD 和 HotPotQA 相同的一般模式。
4 结论
长期以来,AI 中构建模型的主导范式一直围绕着张量表示的乘积,在深度学习时代,这导致了高度模块化(逐层)的设计,这使得快速开发和广泛探索成为可能。然而,这些设计范式需要广泛的领域专业知识,即使是专家在将不同的预训练组件组合成更大的系统时也面临重大挑战。上下文学习的承诺是,我们可以仅使用自然语言作为向系统提供指令的媒介来构建复杂的系统,并且,正如我们所论证的,允许组件之间相互通信。在这种新范式中,构建块是预训练模型,核心操作是自然语言指令和操作自然语言文本。如果我们能够实现这一潜力,那么我们就可以扩大参与 AI 系统开发的人数,快速为新的领域原型系统,并最大化专业预训练组件的价值。
在本论文中,我们介绍了用于检索增强式上下文学习的 DEMONSTRATE–SEARCH–PREDICT (DSP) 框架。DSP 包含了一系列简单、可组合的函数,用于实现上下文学习系统作为深思熟虑的程序——而不是端任务提示——以解决知识密集型任务。我们以 Python 库的形式实现了 DSP 并使用它来编写 Open-SQuAD、HotPotQA 和 QReCC 的程序。这些程序相对于以前的上下文学习方法取得了显著的进步。然而,超越任何特定的性能数字,我们主张 DSP 的核心贡献在于帮助揭示上下文学习在一般概念上的广阔可能性空间。