摘要
近几年,大型预训练语言模型(LLMs)展示出了按照指令行动和利用少量样本完成新任务的能力。这种通过上下文示例对大语言模型进行参数设置的方式,不仅增强了其功能,而且成本远低于微调(finetuning)。我们在这个思路基础上进一步发展,提出了一种新方法:将大语言模型嵌入到一个算法或程序中,从而扩展其能力。为了证明这种方法的有效性,我们展示了一个基于证据的问答示例。这种更注重算法的方法使我们在不进行任何微调的情况下,比传统思维链方法提高了 6.4% 的性能。此外,我们还回顾了这个领域的最新研究,探讨了这种方法与传统方法相比的优势与不足。
机器学习,国际机器学习会议(ICML)
1 引言
通过将语言模型扩充至数百亿参数规模(LLMs)并在数 TB 级别的文本数据上进行训练,已经在众多自然语言处理任务上实现了领先水平的性能。除此之外,这还催生了一种新能力:仅通过指示或少量样本就能学习新技能,正如 GPT-3 所展示的(Brown 等人,2020)。然而,即使经过特定算法能力(如排序或搜索)训练的微调,大语言模型也仍然面临难以展现这些能力的挑战,例如 Anil 等人(2022)、Valmeekam 等人(2022)、Liu 等人(2023)和 Deletang 等人(2023)的研究所表明。
在人类实际操作的数据上进行模型微调(即模仿学习)是一种让模型学习复杂行为的常见方法。例如,在大语言模型(LLM)的领域中,近期的研究通过训练模型学习专家在浏览器(Nakano et al., 2021)或网络商店(Yao et al., 2022)中的交互行为,以提高模型在这些特定任务上的表现。然而,我们有理由怀疑从这些实例中学到的算法的准确性。首先,仅有解码器的 Transformer 语言模型(Vaswani et al., 2017)在计算能力上并不全面,因为它仅能处理有限长度的输入(Fan et al., 2021)。其次,先前的研究表明,即使通过梯度下降来学习简单的程序,这种仅有解码器的架构也难以实现对新情况的泛化(Anil et al., 2022; Deletang et al., 2023)。
除了微调,上下文学习也被用于提升模型执行算法的能力。比如,Zhou et al. 最近提出了一种提示构建方法 (2023b),它能改善大语言模型在执行算术算法方面的能力。这种方法的核心特点是仅需对模型发出一次调用,并使用单一的提示语。然而,这种方法的局限性在于输入的大小限制,以及需要在一个提示语中设计多个算法步骤。作者指出,这可能会导致不同步骤之间的干扰,进而影响模型的最终表现。
我们提出了一种新的方案:将大语言模型 (LLM) 嵌入到程序或算法中。这种方法的关键在于,不是让大语言模型来维护程序的当前状态(即上下文),而是在程序每一步中,仅向大语言模型提供针对该步骤的特定提示和上下文。通过隐藏与当前步骤无关的信息,我们可以专注于解决孤立的子问题,并在未来调用大语言模型时,将这些子问题的结果结合起来。这种直观的做法让大语言模型能够处理更复杂的任务,这些任务目前可能因为能力不足或上下文限制(如上下文大小不足)而难以完成。同时,最新的研究表明,将大语言模型嵌入到一个能与外部存储部件交互的循环算法中,可以使系统在计算上达到通用性(Schuurmans,2023)。
在模型的专业化进程中,嵌入和微调这两种方法都扮演着重要角色,因为它们都注入了特定领域的知识。具体来说,把模型嵌入到一个算法里,或者与一个大语言模型 (LLM) 结合编程,会迫使这个模型遵循一套高级别的程序框架。虽然这可能在某种程度上限制了模型的灵活性,但它也需要对特定任务适用的正确程序有深入的理解。另一方面,微调则涉及到识别和可能需要生成针对特定领域的训练数据,这同样需要高水平的认识和理解。我们认为,在某些情况下,直接将大语言模型嵌入到一个具体的程序中,而不是仅仅在期望的程序执行轨迹上进行训练,可能会更加有效。由于大语言模型训练的难度和成本,我们已经见证了专门针对特定问题设计的大语言模型程序,即使没有进行或仅进行了非常有针对性的训练,也在诸如推理(Kazemi et al., 2022)、问答(Zhou et al., 2023a)、文本摘要(Wu et al., 2021a)、文本生成(Yang et al., 2022b)等具体领域上取得了显著的成效,还有其他领域也有类似的案例(Zeng et al., 2023; Xu et al., 2021; Karpas et al., 2022)。
在这项工作中,我们探讨了用大语言模型 (LLMs) 进行编程的优劣,并介绍了一种我们命名为“Large Language Model Program”的通用方法(见第 2 节)。在第 3 节,我们展示了一个以证据支持问题回答的大语言模型程序示例。为准确作答,该程序先从知识源提取关键事实,再巧妙地融入到回答推理中。程序的示例可见于图 1。接下来,我们将说明这种方法如何适用于其他不同场景,详见第 4 节。
2 大语言模型的局限与其编程优势
大语言模型的形成依赖于三大要素:广泛的并行计算能力、海量数据资源、以及可大规模并行处理的语言模型架构。目前,所有 175 亿参数以上的大语言模型均采用了以解码器为主的 Transformer 架构 (Vaswani et al., 2017)。这种并行处理能力极大提升了大型模型的训练效率,同时大数据的应用也有效避免了模型的过度拟合现象。事实上,在训练过程中,这些模型很少重复使用同一训练数据。
在互联网级数据上训练的大语言模型,能够创造出令人信服的文本,如短篇故事、评论、概述、诗歌等。这些“原始”的大语言模型训练所用的数据既包括维基百科等高质量文本,也包括一些带有偏见和有害内容的低质量文本,因此这些模型在一定程度上也表现出了偏见和有害性 (Dev et al., 2020; Sheng et al., 2021)。
在互联网随机文本上进行训练的大语言模型 (LLM) 面临的一个问题是,它们往往不擅长进行对话、执行指令、使用工具或与环境交互。尽管通过在这类行为实例上进行模型微调 (finetuning) 能够提高其性能(参见 Ouyang et al., 2022; Wei et al., 2022a; Gupta et al., 2022 的研究),但由于缺乏此类数据,这种方法难以大规模实施,并且可能因依赖算法上的简化处理而不具备系统性泛化能力(详见 Liu et al., 2023)。
大语言模型的另一个局限在于其仅有解码功能的 Transformer 架构,这导致它们只能处理有限上下文范围内的信息。尽管这种架构在翻译或语言建模等任务上表现优秀,但它在学习某些算法类别上存在不足,这可能影响其在训练数据之外的泛化应用能力(参考 Csordás et al., 2021 的研究)。
如果大语言模型(LLM)被用于算法的特定特征上进行微调(finetuned),无论是明示还是暗含,这些问题很可能在更大规模上出现。例如,Anil et al. (2022) 在他们的研究中,对参数多达 64B 的 LLM 进行了针对奇偶性问题的变体训练,并发现在稍微长或短于训练序列的情况下,模型性能大幅下降。此外,值得注意的是,长期以来,循环神经网络如长短期记忆(LSTM)已被证明能够在奇偶性和其他基于计数的上下文敏感语言上实现完美的泛化(Hochreiter & Schmidhuber, 1997; Gers & Schmidhuber, 2001; Deletang et al., 2023)。
为了解决这些局限,我们提出了 LLM 程序,这是一种增强基于 LLM 系统能力的新方法。通过 LLM 程序,我们识别并解决了 LLM 作为一个通用智能体的局限性。与其进一步训练模型,我们选择将复杂的预期行为分解成 LLM 能够充分处理的简单步骤,并通过传统的计算机程序(例如 Python)将这些步骤连接起来。该程序负责解析前一个步骤的输出,执行控制流程,并优化后续步骤的指令。
LLM 程序与先前依赖外部系统(如计算器)的研究(Thoppilan et al., 2022)不同的是,程序当前状态的维护不是由 LLM 负责,而是由嵌入 LLM 的程序来完成。这意味着,每次调用 LLM 时,只需包含当前步骤所必需的信息。LLM 程序的几个优点包括:
-
将大语言模型(LLM)整合到程序中,可以大幅提升系统的理论和实践功能,而且这种提升几乎不需要或只需要很少的调整,有助于系统更全面地进行问题泛化。
-
大语言模型程序能将复杂任务分解成多个简单步骤,融入高层次的算法信息,而这几乎不需额外训练。相比之下,仅通过实例学习复杂任务,可能会需要大量的计算资源和高品质数据。
-
了解如何分解问题有助于更准确地为每个子问题或步骤设定输入和输出的标准。这样的规范使得我们可以更有效地并且系统性地通过对每个子问题分别进行测试(无论是通过测试集还是手动检查)来评估大语言模型的性能。
-
在大语言模型程序中,我们会对模型进行多次而非单次查询。每次查询都可能包含针对特定步骤优化的提示,从而提升模型在该步骤的表现。若只向大语言模型发出单一查询,寻找有效的提示可能更困难,因为不同步骤的示例或描述可能会相互干扰,而且提示可能会占用更多已经有限的上下文空间。
总的来说,大语言模型程序为解决大语言模型的局限性、扩展其在各领域的实际应用提供了一条有前景的途径。在接下来的章节里,我们将介绍一个用于问答的大语言模型程序的示例。
3 一个用于问答的大语言模型程序
实用案例。
设想将一个大语言模型 (LLM) 用作公司网站的交互界面。由于这个模型并未针对该网站进行训练,它无法回答关于公司最新产品的具体信息,比如产品特性、规格或是上市情况,也无法告知新开店铺的营业时间。在这个阅读理解场景中,大语言模型因为未经过针对公司网站的训练,且无法将整个网站内容纳入其处理范围,所以表现不佳。对大语言模型进行微调可能并不现实,因为训练这类模型成本高昂,且网站内容经常更新(例如,产品可能突然缺货),需要模型频繁地更新训练。此外,还存在一个问题:经过微调的模型能在多大程度上忠实反映微调数据中的事实仍然是个未知数。
一个更实际的解决方案是使用一个固定状态的大语言模型(即不再更新的模型),让它只能访问网站的最新版本,其中每个网页视为一个单独的文档。鉴于我们无法一次性加载所有文档,我们可以设计一个程序,仔细筛选出回答用户问题所需的关键文档。
数据集。
我们创建了一个数据集,目的是开发一款大语言模型 (LLM) 程序,它能够利用丰富的额外知识资源来回答问题。为此,我们采用了 StrategyQA 数据集(Geva et al., 2021)。StrategyQA 数据集是一种难度较高的问答挑战,它要求参与者通过隐式地连接多个步骤来找到答案。这种问答方式比以往的问答数据集更具挑战性,因为它涉及到复杂的问题拆解技巧和跨领域的深入知识。比如,考虑这样一个问题:“阳光能照到黑海最深的地方吗?”要回答这个问题,LLM 需要知道黑海最深处约 2000 米深,但阳光只能穿透大约 1000 米深的水层。掌握了这些信息后,LLM 就能更容易地找出答案。我们的实验显示,在表 2 中,当 LLM 掌握了所有必要的信息时,其性能最佳。
我们基于 StrategyQA 开发了一个问答数据集。在这个数据集中,每个问题都伴随着大量的知识来源,但其中只有少数真正与问题相关。大部分知识来源是从其他问题中随机抽取的,因此它们通常不包含有用的信息。关键的是,即便是少量的信息段落,对于现有的大语言模型 (LLM) 来说,处理的上下文量已经相当庞大。
StrategyQA 数据集总共包括 2780 个问题,这些问题都附有它们的解析步骤和来自维基百科的证据段落。在这些问题中,大约有 918 个提供了支持所有推理步骤的详细证据。我们选用这部分问题,确保我们提供的额外知识资源能够涵盖推断答案所需的所有信息。否则,我们将需要依赖 LLM 在预训练过程中学到的知识,但这不是我们的出发点。
先前的研究在评估 StrategyQA 基准测试中的问答性能时,得出了不一致的结果(Chowdhery 等人,2022)。这种情况可能是由于个别推理步骤所依赖的事实很少见,难以被人记住,或者是因为推理过程太复杂。尽管采用了更先进的推理方法,如思维链 (Wei 等人,2022b; Nye 等人,2022; Kojima 等人,2022; Wang 等人,2023),但在这个数据集上,即使是配置了 1750 亿参数的大型模型(Srivastava 等人,2022; Taylor 等人,2022)也只实现了轻微的性能提升。然而,模型规模更大,训练时间更长的模型似乎能够带来明显的改进(Chowdhery 等人,2022; Hoffmann 等人,2022)。这表明,在这个数据集中,知识的缺乏可能是比推理能力更大的障碍。
大语言模型 (LLM)。
在我们的实验中,我们使用了一个由 175 亿参数组成的大型原始语言模型 OPT-175B(Zhang et al., 2022)。该模型是通过分析新闻文章、书籍、Pushshift.io Reddit 以及由第三方编纂的数据集 Pile(Gao et al., 2020)上的 3000 亿 Token 训练而成的。因为该模型没有在高质量的指导性或对话性数据上进行过微调,我们将其定义为一个未经特定训练的原始模型。根据 Zhang et al.(2022)的报告,我们发现 OPT-175B 在遵循具体指令上存在困难。然而,我们展示了通过将 OPT 嵌入到一个程序中,我们能够实现更加复杂的行为。
3.1 开发大语言模型程序
在解决基于证据的问答问题时,我们将这一问题分为两部分:筛选和树状搜索。首先,针对给定的问题,筛选部分会遍历所有提供的文本段落,并挑选出最相关的内容。其次,在树状搜索部分,我们会逐步构建推理链条,每一步都生成一个新的推理。在这个过程中,我们可以根据已筛选出的段落来指导推理的方向。这个过程类似于树状搜索,我们会根据一个特定的评分标准来评估每条推理链,然后选择得分最高的链条进行扩展,为每一个证据段落生成 nn 种可能的续篇。这个过程会持续进行,直到找到答案,或者达到预定的最大步数,此时系统将通过计算是或否答案的概率(即负对数似然,NLL)来强制大语言模型给出回答。
示例追踪。
当回答问题,如“能否由 The Police 的成员执行合法逮捕?”时,我们利用大语言模型(LLM)从庞大的信息集中筛选出几段相关文本,许多文本与此问题无直接关联。在本例中,根据 OPT 选择的前 10 个段落就足以涵盖推理正确答案所需的所有关键信息。为了构建强有力的推理链条,我们针对每一步骤使用不同的段落作为背景。整个树形搜索过程围绕着选择哪个段落作为特定步骤的背景。在探讨 The Police 乐队的问题时,最关键的步骤包括了一段关于乐队成员的背景信息。在该背景下,模型首先生成了一步:“The Police 的成员包括 Sting, Stewart Copeland, Andy Summers 和 Henry Padovani。”紧接着,基于另一段提供乐队更多细节的文本,模型推出了第二步:“The Police 的成员并非警察。”之后,模型依据一段解释只有警察才能执行逮捕的文本,得出了下一步:“因此,The Police 的成员无法进行合法逮捕。”最终,模型得出最后一步:“所以,答案是否定的。”,这个答案被认为是正确的。
在接下来的两个小节中,我们将详细探讨大语言模型程序的各个部分。
3.1.1 证据过滤实验
本节介绍了我们在段落过滤环节的方法及其表现。我们通过独立开发和评估每次对大语言模型(LLM)的调用,从而系统地实验、改进和分析整体性能。我们的首次尝试基于少样本(few-shot)示例和对模型进行提示工程(prompt-engineering),以分类给定问题的相关段落。
黑盒式提示。
我们首先尝试的方法是基于少样本(few-shot)提示,利用 OPT 模型来输出一个“是”或“否”的答案,以判断某个段落是否与特定问题相关。这个二元分类的数据集包含了从 StrategyQA 数据中随机选取的 300 个样本,每个样本都包括一个问题及其对应的段落,目的是判断这个段落是否与问题相关。
为了这个子问题,我们精心设计了数据集,一半的问题与从证据段落列表中随机挑选的段落配对,另一半则与其他问题的无关段落配对。这样可以确保相关与不相关段落的平均分布,使得随机基准值保持在 50%。我们在“表 1”中的实验显示,无论是 OPT 还是 InstructGPT(Ouyang et al., 2022)在分类单个段落时都未能达到满意的效果。即便是经过大量不同专业任务训练的 Tk-Instruct(Wang et al., 2022)模型,也无法可靠地识别出相关段落。
这一结果颇为意外,因为对于人类而言,这样的分类任务看似简单明了:通常很难想象一个随机挑选的段落怎么会与问题相关。而且,与问题相关的证据段落通常会包含一些共同的单词或短语,或在语义上与问题有关。鉴于我们独立实验的结果,我们决定探索一种替代方法。
表 1: 使用提示工程手段对单个段落进行的 Top-1 二元分类准确率。随机猜测的准确率为 50%。值得注意的是,如果用这种方法对大量段落进行分类,准确率会显著下降。
方法 | 准确率 |
---|---|
OPT-175B 少样本提示(few-shot prompt) | 53.33% |
text-davinci-002(InstructGPT) | 55.67% |
OPT-175B 少样本 + 思维链(chain of thought) | 56.00% |
tk-instruct 11B | 61.60% |
可能性评估。
在我们的第二种策略中,大语言模型 (LLM) 不再被作为一个不透明的“黑盒”来对待。相反,我们直接利用问题在遵循每个段落时的平均负对数似然 (NLL) 来对所有段落进行排名。为了独立评估这一子问题,我们创建了一个全新的数据集。现在,每个问题由 100 个段落组成,其中一个段落来自于该问题的证据段落清单,其余 99 个则来自其他问题。在此设置下,随机猜测的准确率仅为 1%。值得注意的是,100 个段落的数量远超过了 OPT 模型的上下文处理能力。关于这一点,我们在算法 1(见附录)中提供了伪代码。
即便没有额外
3.1.2 树形搜索实验
在前一节中,我们讨论了程序的过滤部分:评估每个段落的相关性,进行排序,并选出前 nn 个最相关的段落。这个过程可以轻松地扩展到更多的段落,因为段落列表的处理是通过 Python 的 for 循环完成的,而不完全依赖于大语言模型(LLM)的能力。特别是在我们清楚知道最佳算法或行为是什么,以及想要对其进行控制的情况下,这一点尤为重要。
在本节中,我们将介绍一种更为系统的搜索方法,以确保在我们认为最关键的领域实现泛化。与过滤部分一样,我们使用特定的数据集,单独开发和测试这种树形搜索方法。
原始的大语言模型 (LLM) 在回答复杂问题时,无法连接外部系统。这意味着模型只能依赖其权重中存储的、带有噪声、不完整且可能过时的知识。在 StrategyQA 数据集中,很多问题看似需要 LLMs 所没有的知识。因此,我们提出了一种基于证据的思维链条方法。在这种方法中,推理过程分为多个步骤,每个步骤都有相应的支持段落作为上下文。这使得模型能够利用段落中的信息进行原本无法做出的推理。在 StrategyQA 中,大部分问题的解答需要利用不同知识领域的推理步骤。为了找出每个推理步骤中最关键的段落,我们进行了树形搜索,以问题为根节点,每一层包含一系列可能作为下一步骤上下文的证据段落。树上的每一条路径都代表一种推理链。考虑到对所有推理链进行搜索是不现实的,我们对推理链进行排名,并持续扩展排名最高的链条。我们在算法 2 中展示了伪代码(详见附录)。
我们研究了两种推理链排名策略。第一种策略是计算到目前为止整个链条的平均负对数似然(NLL),即在各自段落条件下计算每一步骤的平均 NLL SS。这种方法能让模型扩展到目前为止最可能正确的推理链。这种方法效果不错,但也可能带来问题。我们发现,如果大语言模型(LLM)直接从证据段落 PP 中复制整个短语,这些短语的 NLL 会非常低。这可能导致重复或不断扩展的演绎步骤,最终可能偏离问题 QQ 的本质。我们的第二种排名策略则试图缓解这些问题,它通过计算生成的推理步骤的平均 NLL 差异来排名:考虑有无段落(ΔP Delta_{text{P}}~{})和有无问题(Δ_Q Delta_{text{Q}}~{})。这些经过长度标准化的差值,Δ_P Delta_{text{P}}~{} 和 Δ_Q Delta_{text{Q}}~{},帮助我们选择既利用了所提供的上下文(从而减少了生成错误信息的可能)又保持了话题的相关性(从而减少了思维的发散)的推理链。
在推理过程中,负 (Δ)P left(Deltaright)_{text{P}} &text{nbsp}; 的步骤更多地依赖段落信息,而负 (Δ)Q left(Deltaright)_{text{Q}} &text{nbsp}; 的步骤更多地依赖问题本身,这有助于保持主题的一致性。当我们在两者相加最小的段落上进行推理时,可以得到更好的推理链,从而提高准确性。
表 2: StrategyQA 数据集中完全支持证据的二分类准确率。CoT 代表“思考链”模式。Golden facts 是根据 StrategyQA 数据集中回答问题所需的关键事实。
方法 | 准确性 |
---|---|
OPT-175B, 少样本,无思考链 | 50.33% |
OPT-175B, 少样本,有思考链 | 60.11% |
OPT-175B, 少样本,有树搜索,NLL 排名 | 65.98% |
OPT-175B, 少样本,有树搜索,Delta 排名 | 66.41% |
OPT-175B, 少样本,有关键事实 | 81.27% |
OPT-175B, 少样本,有关键事实,有思考链 | 81.12% |
为了单独评估树搜索的效果,我们假设证据段落包含了回答问题所需的所有推理步骤。然而,并非所有 StrategyQA 问题都符合这一条件,因此我们只选择了其中的 918 个完全符合条件的问题进行研究。
值得注意的是,这种方法是波束搜索(beam search)的一种变体,即一种在有限的范围内优先扩展排名最高的节点来探索问题解决路径的启发式搜索算法。这与语言模型中常用的波束搜索生成文本的方式大不相同,后者在生成下一个词时会从最可能的 kk 个词中选择。我们的方法虽然也是选择最可能的词,但是会在有限的 kk 个段落中进行搜索,以确定用作上下文的内容。
在表 2 的实验结果展示了,相比于 OPT 的链式思考基线,我们的模型在推理能力上已有显著提升。为了更加凸显我们树搜索策略的优势,我们在基准测试中加入了一个特别设置,即在 OPT 的上下文中加入了“关键事实”作为自定义提示。这些关键事实是 StrategyQA 的作者提供的,包含了推理出正确答案所需的全部事实信息。在加入了这些关键事实之后,OPT 的准确率大约达到了 81.2%。这个结果可以看作是 OPT 模型的性能上限,因为它展示了在模型上下文中明确包含所有必要事实时的情况。
4 更多大语言模型程序示例
大语言模型(LLM)的训练是一个既昂贵又复杂的工程任务。这就是为什么这些模型的开发和研究主要在资金雄厚的工业实验室中进行的原因。但近年来,GPT-3(Brown et al., 2020)通过其 API(Brockman et al., 2018)变得易于公众获取,而 OPT(Zhang et al., 2022)和 BLOOM(Scao et al., 2022)系列的模型权重也已公开,这促进了大量的大语言模型研究。
近期一些工作隐含地采用了我们展示的大语言模型程序化方法。这些研究通常以阶段或算法的形式出现,通过不同的提示语对各个步骤进行参数化。在这一节中,我们将梳理所有采用这种新兴方法的最新和并行研究。
Creswell & Shanahan(2022)把答案的推导过程分解为一个循环算法,包括选择、推断步骤和终止准则。每个步骤都采用了经过微调的大语言模型,这些模型只能访问必要信息,以避免学习如直接从问题预测答案这样的捷径。与基准相比,这套系统在发现证据方面的能力提高了 20% 以上。
Yang 等人 (2022c) 提出了一种新颖的方法,该方法能够从自然语言描述的事实中提取出规则。他们利用大语言模型 (LLM) 根据提供的事实和规则模板,生成一系列可能的规则。随后,通过改变提示词,使用同一个大语言模型进行四次筛选,排除那些不符合必要归纳标准(如过于简单)的规则。他们展示了整个系统及其各个模块的实验结果,证明了这一五步流程的有效性。
与此同时,其他研究建议使用验证器 (verifiers) 来通过重复验证的方式提升生成样本的质量(Cobbe 等人,2021)。例如,Saparov 和 He (2023) 使用不同的提示词,反复验证每个步骤,这种方法在不需要微调的情况下,显著提高了结果的准确度。
Kim 等人 (2021) 提出了一个三步骤的流程,用于识别问答场景中的不成立预设。例如,问题“哪位语言学家发明了电灯泡?”错误地假设了有语言学家发明了电灯泡。他们发现,在流行的自然问题数据集(Natural Questions,Kwiatkowski 等人,2019)中,这样的虚假预设占了无法回答问题的很大一部分。他们的程序首先生成预设,然后验证这些预设,最后给出解释。研究者们尝试了不同的策略,分别使用神经网络和基于规则的模型处理不同的步骤,并对每个步骤单独进行了测试。
目前在语言模型中进行推理的主要方法是正向链式推理,即从确定的事实出发,在规则的空间里搜索,直到找到目标陈述。这包括我们在3.1.2 节中介绍的方法。然而,Kazemi 等人(2022)认为,反向链式推理更为有效,这种方法是把目标陈述分解,直到能从已知事实中证明这些子目标。基于这一点,他们实现了一个包含四个模块的反向链式推理系统:事实检查、规则选择、目标分解和符号一致性。每个模块都是用预训练的大语言模型(LLM)和特制的提示语实现的,并作为 LAMBADA 程序的子程序。得益于大语言模型的能力,这些模块保持较高的水平,使整个程序相对简单,只包含两个嵌套的 for 循环。LAMBADA 方法在效果上显著优于其他方法,如思维链条推理(Wei 等人,2022b)和选择 – 推断方法(Creswell & Shanahan,2022)。
在相关的研究中,有一种方法是首先将复杂的原始问题分解为更简单的子问题,以便更易于解答。通过回答这些子问题,一个专门的模块能够解答原始问题。Patel et al. (2022) 运用了由人类分解的问题,这大幅提升了性能。而 Zhou et al. (2023a) 则使用大语言模型 (LLM) 自动进行问题分解。他们的实证研究显示,这种方法在效果上显著优于“思路链式提示” (chain of thought prompting)。不过,与先前的方法不同,这些作者在单次调用大语言模型 (LLM) 时完成问题分解,而非采用循环算法。因此,在处理更为复杂、超出常规分布范围的案例时,这种方法可能更易出错,因为在一个紧凑的步骤中,输出规格的可能性要远大于像 LAMBADA 这样的分步程序。关于更多分解的例子,可以参考 Perez et al. (2020) 和 Yang et al. (2022a) 的研究。
常规大语言模型 (LLM) 是独立运作的系统,只能访问存储在其权重中的信息。正如我们在第 2 节讨论的,这类系统可能缺乏执行某些任务所需的信息。引入一个额外的,可能是非神经网络的系统,可以作为增加模型规模的替代方案。例如,Lazaridou et al. (2023) 创造了一个谷歌搜索查询,其结果作为上下文加入到问答提示中。这种提高事实性和准确性的做法证明了“推理型”干预 (inference-type interventions) 的益处,即在推理过程中,通过简单的程序将模型集成,使系统能够利用传统文档检索系统的结果,而不必依赖专用的检索增强模型。
有趣的是,大语言模型 (LLM) 并不总能有效利用其模型权重中存储的知识。Liu et al. (2022b) 展示了一个两步程序,这个程序首先产生与特定问题相关的一组事实,然后再回答问题,这种方法被证明能够提升性能。类似的方法还可见于 Paranjape et al. (2021) 和 Li et al. (2022) 的研究。Liu et al. (2022a) 进一步通过基于问答性能提升的强化学习方法来改善这种知识提取过程。另外,Cohen et al. (2023) 的研究则探讨了如何利用多步程序从语言模型中提取知识库。
在问答之外,我们也看到了大语言模型在生成性任务上的应用。Yang et al. (2022b) 利用递归的方式让大语言模型根据故事计划和当前故事状态来生成长达 2500 词的连贯故事。而 Wu et al. (2021b) 则展示了如何通过递归地总结固定大小部分的先前摘要来总结整本书。这两种方法都是克服了仅有解码器的 Transformer 模型的有限上下文限制的递归程序的优秀例子。
在另一项研究中,大语言模型 (LLMs) 被用于持续的模型与环境交互中,以帮助机器人根据给定的高级目标制定计划并提出建议 (Ahn et al., 2022; Huang et al., 2022)。但是,目前的做法是将所有环境信息提供给大语言模型,而没有办法更新外部存储的信息。这导致在一些极端情况下,模型处理的输入和输出可能超出了当前大语言模型的处理能力。
在一个迅速发展的研究领域中,研究者进一步扩展了大语言模型与环境互动的概念。这些研究将大语言模型的能力与另一种联结主义或传统系统的优势结合起来。例如,有些大语言模型能够反复生成短小的可执行程序,作为中间推理步骤 (Gao et al., 2022);有的则在生成国际象棋评论时,借助符号逻辑引擎 (Lee et al., 2022);还有的模型能够利用各种其他工具,比如计算器 (Karpas et al., 2022)。
在未来,我们预计会见证到更多精密复杂的算法的诞生,这些算法将整合多种神经网络和符号处理模块,以应对越来越复杂的任务。为了支援这类项目,近期已经有新的编程库被开发出来。LangChain(Chase,2023)是一种库,它帮助开发者将大语言模型 (LLM) 与其他计算资源相结合。GPT-Index(Liu,2022)则是一组数据结构的集合,用于简化将外部知识库与大语言模型 (LLM) 结合使用的过程。Reppert 等人 (2023) 推出了 ICE,这是一个开源工具,用于可视化语言模型 (LM) 程序的执行轨迹。
近期的研究还探讨了大语言模型程序的益处。Wu 等人 (2022b) 研究了用户在自行编写大语言模型程序时的需求,并提出了 PromptChainer,这是一个支持构建应用原型的工具。Wu 等人 (2022a) 则展示了一个互动式的“连锁编撰系统”,并研究了用户如何通过修改这些系统来提高性能和用户满意度。
通用程序
在人工智能领域,一个新兴而又引人注目的研究方向是开发不依赖特定任务的大语言模型(LLM)程序。目前,这类程序还没有得到广泛的关注。例如,Shuster 等人在 2022 年的一篇论文中 (2022a),提出了一个新系统。这个系统通过在回答用户问题之前先进行知识检索,从而增强了对话智能体的能力。同样,Shuster 等人在另一篇论文 (2022b) 中介绍了 BlenderBot 3,这是一个基于大语言模型的对话机器人。与传统机器人不同的是,它配备了长期记忆存储功能,能够记住用户在不同会话中的信息,这是像 ChatGPT (由 Schulman 等人在 2022 年提出的 2022) 无法做到的。Dalvi 等人在 2022 年的研究 (2022) 中采取了另一种方法。他们使用了一个基于对话树的简单程序,让机器人从用户那里学习信息。这些信息被存储在一个可以更新的动态记忆库中。最重要的是,这个程序包括一个用户交互循环,用户可以通过这个循环纠正机器人的错误,机器人随后会更新其动态记忆库。因此,这个程序可以看作是一个实现了基础学习算法的大语言模型实例。这一发现为未来的研究开辟了新天地,特别是在像 Optimal Ordered Problem Solver 或 Gödel Machine 这样的符号学习算法方面(由 Schmidhuber 在 2004 和 2007 年提出的 2004, 2007)。
5 讨论与相关研究
我们提出的使用预训练模型编程的方法,与通常训练一个单一且功能全面的“黑盒”深度学习模型的理念不同。通常这样的模型只需在参数数量和训练数据上扩展即可。虽然这是大语言模型 (LLM) 当前成功的核心,但这种方法存在一些缺点:
-
如大型预训练的 Transformer 语言模型这样的深度神经网络模型,它们的计算过程难以理解(有相关研究正在进行,例如参见 Elhage et al. (2021))。通过将问题分解成多个步骤,我们不仅可以提升性能,还能让推理过程更容易理解。
-
LLM 是在包含有害、偏见或其他不良内容的大量文本上训练的。因此,LLM 也可能产生不希望的文本输出。而语言模型本身并没有防止这种输出的安全机制。将 LLM 嵌入到程序中,能有效引入安全机制,例如过滤掉不需要的 LLM 响应。
-
对复杂行为进行 LLM 微调需要大量高质量的特定行为数据,这些数据难以获取且成本高昂。将问题分解为子问题可以帮助我们识别缺失的特定低级功能。集中精力收集这些盲点的数据可能是一种更快更高效的方法,而且这些低级功能对许多问题都可能有用。
-
由于解释性不足,很难对神经网络模型提供任何形式的保证。此外,神经网络在数据分布之外的泛化能力较弱是众所周知的。但是,将一个或多个神经网络模块嵌入程序中,可以提供一些简单的泛化保证,这在其他情况下是不可能的。例如,我们程序中的过滤和搜索部分,如第 2 节所述,可以轻易地扩展到更多段落。
-
到目前为止,所有参数数量达到 1000 亿以上的大语言模型 (LLM) 都基于 Transformer 架构。因此,它们也继承了此架构的限制,比如只能处理几千个 Token 的有限上下文(参见 Hutchins et al., 2022)。一种解决方法可能是将大语言模型集成到一个独立于任务的程序中,该程序负责筛选并将相关文档引入上下文,或对过去的文本进行总结。
我们认为,本文提出的利用大语言模型进行编程的方法,能够在理解查询处理的场景中减轻许多不足之处。很多近期的论文已经证明了这种做法的好处(详见前文第 4 节),但较少有论文从更高的角度进行探讨。这里,我们介绍一些与我们总体思路相似的最新或同时期的研究。
与我们研究同期的 Khot et al. (2023) 提出了一种名为 Decomposed Prompting 的框架。该框架通过将任务分解为可由大语言模型单独解决的子任务,并为每个子任务设计特定提示。作者在简单的字符串处理和问答任务上展示了其优越的适应性能。
在之前的研究中,Dohan et al. (2022) 提出了一个有趣的观点,将预训练模型组合起来,就像在编写概率性的程序一样。在这种被称为语言模型级联的方法中,大语言模型(LLMs)被视作概率程序中的字符串类型变量。这种视角下,作者们整合了各种现有算法,如思维链路(Wei et al., 2022b)、便签本(Nye et al., 2022) 或 STaR(Zelikman et al., 2022),从而提供了一个更为全面的算法视角。
同样地,Creswell & Shanahan (2022) 简要介绍了他们的方法,称之为“算法式提示”,即将语言模型对初始提示的响应融入后续的提示中。他们认为,这样的提示设计和应用可以整合成完整的算法,以实现更复杂的行为。在接下来的研究中,Shanahan (2022) 进一步强调,这种方法对于构建一个可靠的推理系统是必不可少的。
Zeng et al. (2023) 提出了一个由多个预训练模型组成的模块化框架,这些模型组合在一起,能够在无需进行全面训练或细微调整的情况下,掌握新的多模态技能。
另一个不同但相关的思路是,Giannou et al. (2023) 将一个循环的 Transformer 模型描述为“可编程计算机”。通过一个简单的循环过程,他们反复调用带有便签、内存和指令的 Transformer 模型,这一过程与编写计算机程序有相似之处。
我们的方法灵感来源于 Schmidhuber 在 2015 年的“学习思考”报告(第 5.3 节),其中介绍了一种控制器网络 CC 学会向另一个网络 MM 发送激活序列,随后读取 MM 的激活信息以利用其知识。但与报告中的描述不同,我们的程序并非一个训练过的神经网络,而是一个明确定义的算法。
6 结论
我们介绍了一种新兴的 LLM(大语言模型)程序设计方法。这种方法是将预训练的连接模型(如大语言模型)集成到传统程序中,用以处理更加复杂的任务。其核心思想是递归地将主问题拆解为多个子问题,直至每个子问题能够通过单次查询模型得到解决。通过为每个子问题设定更精确的输入输出规格,我们可以独立地开发并测试模型的性能。我们以证据支持的问题回答场景为例,展示了这种方法如何在不需要微调的情况下提升性能。此外,我们还总结了这种方法的优势和不足,并着重介绍了近期在这一领域的研究进展。
附录 A 算法
A.1 排名算法
算法 1 描述了如何通过计算问题与段落内容的平均负对数似然来对段落进行排名,并选择排名最高的前 n 个段落。
Input: question qq, paragraphs PP, nn
initialise: nlls =[]=[quad]
for paragraph pp in PP do
avg_nll=LLM(q,p)text{avg_nll}=text{LLM}(q,p)
nlls.append((i, avg_nll))
end for
return sorted(nlls)[:nn]
A.2 树搜索算法
算法 2 展示了基于排名标准 rr 对不同证据段落进行树形搜索的过程,这些证据段落是通过排名算法从众多段落中筛选出来的。
Input: question qq, paragraphs PP, criteria rr
initialise: chains =[[q]]=[[q]], complete =[]=[quad]
while len(complete)<=3text{len}(text{complete})<=3 do
c=pop(sort(chains,criteria=c=text{pop}(text{sort}(text{chains},text{criteria}=r))))
for paragraph pp in PP do
c′=add_step(c,p)c^{prime}=text{add_step}(c,p)
if gives_answer(c′)text{gives_answer}(c^{prime}) then
complete.append(c′)text{complete.append}(c^{prime})
else
chains.append(c′)text{chains.append}(c^{prime})
end if
end for
end while
return complete