Revisiting Prompt Engineering via Declarative Crowdsourcing-声明式提示工程

时间:2024-11-19 11:39:43

    我们设想了一个围绕 LangChain 等工具的包装器,其中包含单独的数据处理原语,例如排序、过滤、连接、分类、聚类、查找、填充、解析等,可应用于一个或多个数据集。用户还可以提供总体预算和期望的准确性。此外,用户还可以提供“黄金标准”测试答案以及与手头任务相关的特殊提示模板——这些模板也可以从存储库或指南中提取 [1, 5, 15, 49] 接下来,我们将描述从众包文献中提取的一系列原则,我们可以利用这些原则并扩展这些原则以实现快速工程。我们还包括一些案例研究,以说明使用这些原则、利用各种 LLM、问题和数据集的好处。对于所有案例研究,我们将 LLM 温度设置为 0。

在这里插入图片描述
表 1:对 20 种口味进行分类的结果,展示了提示策略中成本和准确性之间的权衡。

    不同的提示策略 LLM 的用户通常使用单个任务来完成他们的整个目标。例如,如果他们想要根据情绪对多个文本片段进行排序,他们会将它们全部放在一个任务中,并要求 LLM 对它们进行排名。众包文献告诉我们,有多种方法可以实现同一目标,通常具有不同的成本/准确性权衡。对于特定的排序任务 [39],可以使用成对比较(其中给定任务涉及一次比较一对数据项),而不是使用单个任务对整个数据项集进行排序,其中给定任务涉及一次比较一对数据项,总共有 O(n2 ) 个任务。另一种方法是使用 O(n) 任务征求每个项目的评分,并使用这些评分进行排序。在这种情况下,我们期望更细粒度的方法在准确性方面比更粗粒度的方法表现更好,但成本更高。类似地,对于计数 [37],一种选择是使用粗粒度任务来估计满足某些属性的数据项的比例(通过“目测”),而不是以细粒度的方式单独检查每个数据项。最后,对于实体解析 [57],可以使用粗粒度任务,将多个数据项分组为相同的集合,也可以使用细粒度任务,一次比较成对的数据项。因此,对于所有这些任务,如果我们想保证更高的准确性并且成本不那么重要,那么使用更细粒度的单元任务会更有优势,而不是简单地要求 LLM 在一个任务中解析、排序或计数项目。

    通过三种提示策略进行排序的案例研究。在这里,我们探索了使用上述三种方法进行排序:

  1. 列出提示中的所有项目并要求 LLM 对列表进行排序 - 这是我们的基本方法,
  2. 使用 O(n2) 成对比较,每个比较作为单独的任务,然后根据给定数据项“赢得”的成对比较总数进行排序,任意打破平局,最后
  3. 为每个数据项获得 1(最低)-7(最高)的评级,然后根据这些评级进行排序,任意打破平局。

    具体来说,我们使用了 OpenAI 的 GPT-3.5-turbo 模型,根据 20 种冰淇淋口味的“巧克力味”程度对其进行排名,将结果与人工标记的真实排序进行比较,该排序已由论文的两位作者验证。真实排序包含列表开头以“巧克力”开头的口味和结尾以水果相关的冰淇淋(如“柠檬冰糕”)开头的口味。对于我们的基准方法,我们发现 LLM 将标题中带有“巧克力”的口味排在列表开头,而其余的排序似乎是随机的——这种方法的 Kendall Tau-β 得分——比较排名的标准指标——为 0.526。成对比较策略需要对 LLM 进行 20 次 2 调用,得分为 0.736,而基于评级的策略得分为 0.547。我们列出了分数以及以 token 为单位的总输入和输出大小——这决定了成本——见表 1。总体而言,我们发现不同的策略提供不同的成本-准确度特征,成对方法的成本和准确度最高,基线方法的成本和准确度最低,而评级方法在两个方面都处于中间位置。要点:与其试图通过单一任务完成整个目标,不如探索其他任务类型,特别是为了最大限度地提高准确度。

在这里插入图片描述
表 2:按字母顺序对 100 个单词进行排序的结果,共 3 次试验。要求 LLM 执行比较以插入原始排序中遗漏的单词可提高性能。

    混合粗粒度 → 细粒度提示在我们之前的案例研究中,通过一次 LLM 调用完成整个任务是可行的——即使它导致整体准确度较低。这是因为我们有相对较少的数据项供 LLM 排序。随着数据项数量的增加,尽管 LLM 具有高上下文窗口,但 LLM 甚至很难完成任务。响应容易出错,出现随机幻觉(引入新数据项)和低召回率(省略旧数据项)。最近的研究还表明,LLM 在很大程度上忽略了长提示“中间”的文本 [33]。在这种情况下,使用多种类型的任务来实现目标是有利的,通常先使用粗粒度任务,然后再使用细粒度任务。

    众包中也应用了类似的策略。例如,为了在一组项目中找到最大值,Khan 等人 [24] 使用了两种类型的任务:成对比较任务和评级任务。后者更适合在早期阶段进行粗粒度的分级,而前者可用于对具有较高评级的项目进行细粒度比较。事实证明,这种方法比仅利用评级的方法具有更高的准确性和更低的成本,并且比仅利用成对比较的方法具有更低的成本。
类似的混合方法也用于排序 [39]。

    对于聚类,Jain 等人 [22] 采用两阶段过程来识别合适的聚类方案,然后对聚类中的剩余项目进行分类。对许多项目进行排序的案例研究:排序 → 插入。我们再次考虑排序,使用更多的项目,以调查它是否会导致幻觉和遗漏单词。为了使我们能够以编程方式考虑对大量项目进行排序,我们从字典中生成了一个 n = 100 个随机英语单词的列表,目标是按字母顺序对单词进行排序——我们希望 LLM 能够很好地完成这项任务。然后,我们使用与第 3.1 节相同的基线方法,我们将整个单词列表提供给 LLM(Anthropic 的 Claude 2),并要求它按排序顺序返回单词。在三次试验中,按字母顺序排序单一提示导致 LLM 回答中 4-7 个单词缺失,0-1 个单词是幻觉。在表 2 中,我们还报告了在随机位置插入缺失项目后的 Kendall Tau 分数。
在这里插入图片描述
表 3:在 DBLP-Google Scholar 数据集的一部分中识别重复引用的结果。在更多邻居之间加强成对比较之间的一致性可以提高 F1 分数。

    为了改进这种方法,我们考虑了一种从粗粒度到细粒度的混合提示策略,我们首先要求 LLM 对整个项目列表进行排序。然后,我们删除了所有幻觉词。最后,为了将缺失的单词重新插入到排序列表中,我们要求 LLM 将每个缺失的单词与部分排序列表中的其他单词进行成对比较(即,O(kn)调用 LLM,查找 k 缺失的单词)。一种简单的推导插入缺失单词 wi 的索引的策略是找到 LLM 认为小于 wi 的第一个排序词;但是,这种方法的效果可能很差,因为 LLM 不能保证正确排列每对单词,而早期索引的错误可能会不成比例地惩罚最终的排序。相反,我们将每个单词 wi 与所有已排序的单词进行比较两次(一个提示中 wi 列在第一位,另一个提示中 wi 列在第二个位),以解决 LLM 中存在的任何排序偏差。然后,我们通过最大化所有 wi 比较的“对齐”来得出它的索引。也就是说,我们选择了 wi 中倒置成对比较结果数量最少的位置。在 3 次试验中,即不同的 100 个单词列表,这种插入策略给出了近乎完美的最终排序,平均 Kendall Tau-β 统计量为 0.990;并且由于插入,这个过程结束时缺失项的数量很容易就变成了 0。总结:采用混合策略,先进行粗粒度任务,然后进行细粒度任务,可以降低成本,提高整体准确率。

    确保内部一致性当给定问题涉及发布一批相互关联的任务时,可以在任务之间强制一致性,以提高每个单独任务的准确性。例如,考虑实体解析,让 LLM 一次比较一对实体。如果 LLM 说实体 A 与实体 B 相同,而实体 B 与实体 C 相同,那么要么 C 与 A 相同,要么前两个比较之一不正确。换句话说,一批成对的实体解析任务的实体解析必须尊重传递性。这种确保一批任务一致性的方法已经应用于众包中的一些问题。例如,对于二分图上的实体解析(可以表述为模糊连接),Wang 等人 [58] 利用传递性进行序列比较,通过避免明显的匹配和不匹配来降低成本。类似地,人们可以确保排序和最大值确定问题中的内部一致性,例如 [19],其中给定一组成对比较(即 a > b),目标是识别那些不正确的比较,这样我们就可以确保全局拓扑排序顺序或最大值的全局共识。在某些准确度模型下,翻转导致拓扑排序的最小边数会导致最大似然排序顺序或最大项。鉴于 LLM 会随机犯错,我们预计它们经常会违反内部一致性——因此事后修补其结果有助于提高准确性。

在这里插入图片描述
表 4:使用 LLM 和非 LLM (k-NN) 策略进行缺失值插补任务的结果。k-NN 算法的 k = 3。即使在提示中包含 k = 3 个相邻示例,以提高 LLM 性能,混合方法也能实现与“LLMonly”策略类似的性能,同时显著减少对 LLM 的调用次数。

    在强制内部一致性的同时进行实体解析的案例研究。我们考虑将这个想法应用于 DBLP-Google Scholar 引文数据集上的实体解析任务 [28]。先前的工作已经根据该数据集设计了一组问题,包括训练集、验证集和测试集,其中每个问题比较一对引文 [13]。我们将实验限制在 5742 对的验证集上。作为基线,对于每个问题,我们询问 LLM(OpenAI 的 gpt-3.5-turbo 模型)两个引文是否重复。我们使用的提示是“引文 A 和引文 B 是否相同?是或否?引文 A 是……引文 B 是……引文 A 和引文 B 是否相同?从是或否开始回答。”基线方法的 F1 得分为 0.658,具有高精度(0.952)和低召回率(0.503)。对于实体解析任务,回忆重复项非常重要,因此我们希望利用内部一致性来提高回忆率。

    利用内部一致性的一个简单方法是,如果通过传递性,两个引用是重复的,则将 LLM 的“否”响应翻转为“是”。例如,标题为“indexing the positions of Continuousl…”和“bindexing the positions of Continuous…”的论文未被基线标记为重复,但两者都是“indexing the positions of Continuousously…”的重复,因此它们的边可以翻转为重复。由于验证集相对于实体数量而言是稀疏的,因此传递边的数量非常少。因此,我们通过额外的比较扩充了验证集。我们使用 OpenAI text-embedding-ada002 模型为每个实体创建嵌入,并根据嵌入空间中的 L2 距离确定相邻的引用。

    对于我们数据集中的每个问题,如果一个问题有两个引文 A 和 B,我们会考虑每个引文的 k 最近邻居(即 O (2k) 引文),并要求 LLM 比较引文集内的每对引文及其邻居(即 2k 2 对)。如果 LLM 发现从 A 到 B 的某些“路径”,其中两个引文之间存在边,当且仅当 LLM 认为这些引文重复,那么我们也会将 A 和 B 标记为重复,即使 A 和 B 之间没有边。我们尝试了 k = 1 和 k = 2,发现 F1 分数增加了 6% 以上,如表 3 所示。这种基于传递性翻转“否”边的简单策略在提高此设置中的 F1 分数方面非常有效,因为它提高了召回率,同时略微降低了准确率。作为未来的工作,为了同时提高准确率和召回率,可以考虑根据是否有足够的反方向证据来翻转“是”和“否”边。总结:根据其他答案的证据来修复错误的 LLM 答案可能是提高准确率的有效方法。

    利用 LLM 和非 LLM 方法,降低成本的一个有用方法是完全避免 LLM 调用,特别是对于那些有更便宜的代理的任务。 例如,假设我们可以使用低成本方法(例如更便宜的开源 LLM 或其他模型)以高概率判断 LLM 对给定任务的响应是什么。然后,我们可以避免询问 LLM,而是将预算节省下来用于真正需要它的其他任务。例如,对于实体解析,Wang 等人 [57] 使用混合人机工作流程进行实体解析,仅众包比较超过廉价模型确定的某个可能性阈值的实体对。在这种情况下,更便宜的代理是预先确定的。

    在其他情况下,可以使用 LLM/crowd 确定这个更便宜的代理。例如,Marcus 等人 [39] 利用众包提取每个实体的特征,并将它们用作过滤器来确定是否需要为了实体解析而比较实体。类似地,Gokhale 等人 [18] 使用众包来推导实体解析的分块规则,然后使用众包来比较每个分块内的实体,之后他们训练一个 ML 模型,以避免必须向众包询问每个实体对。类似的想法也适用于 LLM。人们可以使用由人类专家构建的低成本非 LLM 模型,并且只向 LLM 询问困难案例。或者,鉴于 LLM 可以合成程序,人们可以使用 LLM 编写代码来训练给定特定任务的模型,例如实体解析或数据插补。在这两种情况下,都可以默认使用低成本模型,对于存在不确定性的情况(由模型置信度得分确定),我们可以利用 LLM。

    结合 LLM 和非 LLM 方法进行数据插补的案例研究。我们探索使用 k-最近邻 (k-NN) 作为非 LLM 策略,并专注于对具有缺失属性值的记录进行数据插补。具体来说,对于每个这样的记录,k-NN 从邻居属性值的众数或最常出现的值中推断缺失属性。基于 LLM 的策略要求 LLM(此处为 Anthropic 的 Claude 模型)根据实体中已知属性的序列化表示来预测缺失属性的值。序列化实体 e 具有 j 属性 a1 . . . aj 和值 e1 . . . ej,其中 ej 缺失,其列表如下:a1 为 e1;a2 为 e2;… . . aj−1 为 ej−1。我们最终考虑了一种混合方法,如果所有邻居都包含相同的缺失属性值,则使用 k-NN 估算的值——否则,LLM 将被提示返回缺失值。因为在这种情况下,我们有一组具有基本真值的记录(由 kNN 使用),我们可以选择在混合和 LLM-Only 方法中将示例插入 LLM 的提示中,因为示例有助于提高准确性 [34],同时也会增加成本(就输入标记而言)。总体而言,我们考虑了五种方法:kNN、LLM-Only(没有示例)、混合(LLM 调用中没有示例)、LLM-Only(有 k ′ = 3 个示例)和混合(LLM 调用中有 k ′ 示例),结果显示在表 4 中的 Restaurants 和 Buy 数据集 [41] 上。

    首先关注无示例设置,我们发现混合方法的表现优于非 LLM 和 LLM-only 策略,成本大约是 LLM-only 策略的一半。值得注意的是,在这种情况下,混合方法比仅使用 LLM 的方法表现更好,因为仅使用 LLM 的方法有时会估算与基本事实不完全匹配的值(例如,“TomTom”而不是“Tom Tom”或“Elgato Systems”而不是“Elgato”),因此可能受到不公平的惩罚。添加示例后,混合和仅使用 LLM 的策略都会变得更加昂贵,但混合方法在一个数据集上实现了相同的性能,在另一个数据集上实现了稍差的性能,而成本大约是仅使用 LLM 策略的一半。要点:利用非 LLM 代理可以帮助大幅降低成本,同时保持相似的准确性。

    质量控制确保 LLM 准确性的主要方法是检查 LLM 输出的答案是否违反某些句法约束(例如,0 表示是/否答案),然后重试查询。我们建议借鉴众包的想法,使其更具原则性。第一个挑战是理解 LLM 对于给定类型的任务的准确性。按照众包文献中的最佳实践 [11, 26],一种方法是通过验证集来实现这一点,验证集的基本事实答案是已知的——人们可以根据正确的分数推断出准确性。在没有验证集的情况下,我们可以对同一任务的一组 LLM 应用期望最大化类型的方法 [21],其中的基本假设是每个 LLM 独立回答任务,并且对该类型的任务具有固定但未知的准确性。其他质量控制方法包括验证 [6, 31] LLM 验证自己的响应作为后续,或让另一个 LLM 这样做。类似的想法在 LLM 中表现出了前景 [36]。最后,人们还可以尝试消除偏见或更好地校准 LLM 答案,就像在众包中一样 [52, 71]——已经有一些校准 LLM 的早期尝试 [69],但仍有更多工作要做。

    一旦我们知道了每个 LLM 对给定任务的准确率,我们就可以应用一些技术来确定在每个步骤中要询问哪个 LLM,以确保总体上达到给定的准确率,同时保持较低的成本。特别值得注意的是从众包中借鉴的概率方法 [45],我们根据迄今为止的答案来确定是否值得询问另一个 LLM,或者最终确定一个答案——那些在 LLM 之间存在更多分歧或每个 LLM 的置信度较低的数据项比那些在​​ LLM 之间存在高置信度或一致的数据项更值得花钱。类似的方法已经证明对于推理任务来说,即使对于单个 LLM [59] 来说,这也是一个承诺,其中提取多个推理路径,然后通过多数投票得出最终答案。