Skip to main content

· 11 min read
Yiran Wu

MathChat 工作流程 简介:

  • 我们介绍了MathChat,这是一个利用大型语言模型(LLM),特别是GPT-4,来解决高级数学问题的对话框架。
  • MathChat在解决具有挑战性的数学问题时提高了LLM的性能,比基本提示和其他策略提高了约6%。在代数类别中,准确性提高了15%。
  • 尽管有所进展,但GPT-4仍然难以解决非常具有挑战性的数学问题,即使采用了有效的提示策略。需要进一步改进,例如开发更具体的助手模型或集成新的工具和提示。

最近的大型语言模型(LLM)如GTP-3.5和GPT-4在各种任务上展示了令人惊讶的能力,例如文本生成、问题回答和代码生成。此外,这些模型可以通过对话与人类进行交流,并记住先前的上下文,使人类更容易与它们进行互动。这些模型在我们的日常生活中扮演着越来越重要的角色,帮助人们完成不同的任务,如写电子邮件、总结文件和编写代码。

在本博客文章中,我们探讨了LLM的问题解决能力。具体而言,我们对它们解决高级数学问题的能力感兴趣,这可能代表了一类需要精确推理并具有确定性解决方案的更广泛问题。

我们介绍了MathChat,这是一个用于解决具有挑战性数学问题的对话框架,利用了最先进的LLM的聊天优化特性。该框架利用用户代理和LLM助手之间的对话模拟来解决数学问题。我们还测试了之前的提示技术以进行比较。

MathChat框架

MathChat模拟了LLM助手和用户代理之间的对话。正如名称所示,用户代理充当用户的代理,负责与LLM助手进行通信并以所需的方式继续对话。

用户代理首先向LLM助手提出一个数学问题,并通过初始提示来指导助手在解决问题时如何进行协作。我们采用了现有的提示方法,如CoT(思维链)和使用工具的提示。提示的关键组成部分包括:

  • 使用工具的提示: 这指导LLM助手使用正确格式的Python代码来解决问题,使用户代理能够解析代码并提供适当的结果。

  • 问题解决策略选择提示: 助手被指示选择三种潜在的问题解决策略,包括:

    1. 编写一个Python程序直接解决问题。
    2. 不使用Python直接解决问题,这样可以锻炼LLMs固有的推理能力。
    3. 使用Python逐步解决问题。当前两种策略不适用时,应使用此策略。
  • 最终答案封装提示: 这部分指示助手将最终答案放在 \boxed 中。

MathChat中的提示设计灵活,可以轻松地进行改进,包括添加其他工具,如Wolfram Alpha。

让我们来看一个用户代理人LLM助手(GPT-4)之间的示例对话。对话集中在如何使用Python解决不等式问题上。 (为了易读性,对话进行了修改。)

参与者对话
用户代理人(初始提示:让我们使用Python解决一个数学问题...)问题:找出所有满足不等式(2x+10)(x+3)<(3x+9)(x+8)的x。用区间表示你的答案。
LLM助手解决这个问题的关键思想是找到临界点,即不等式相等的点。然后,测试临界点之间的区间,找到不等式成立的区间。
LLM助手(继续)这是用Python代码找到临界点的方法:from sympy import symbols, Eq, solve; x = symbols("x"); lhs = (2*x + 10)*(x + 3); rhs = (3*x + 9)*(x + 8); equation = Eq(lhs, rhs); critical_points = solve(equation, x); critical_points
用户代理人临界点是:[-14, -3]

实验设置

我们评估了MathChat带来的改进。

在实验中,我们专注于来自MATH数据集的5级问题,这些问题由高中竞赛问题组成。这些问题涉及定理的应用和复杂方程的推导,即使对于本科生来说也具有挑战性。我们评估了数据集中的6个类别(几何学除外):初等代数,代数,数论,计数与概率,中级代数和预微积分。

我们评估了GPT-4,并使用OpenAI API的默认配置。为了获得最终的性能,我们手动将最终答案与正确答案进行比较。对于原始提示、思维程序和MathChat,我们让GPT-4将最终答案放在_\boxed_中,并将PoT函数的返回值作为最终答案。

我们还评估了以下方法进行比较:

  1. 原始提示: 评估GPT-4的直接问题解决能力。使用的提示是:“仔细解决问题。将最终答案放在\boxed中”。

  2. 思维程序(PoT): 使用零-shot的PoT提示,要求模型创建一个_Solver_函数来解决问题并返回最终答案。

  3. 程序合成(PS)提示: 类似于PoT,它提示模型编写一个程序来解决问题。使用的提示是:“编写一个程序来回答以下问题:{Problem}”。

实验结果

不同方法在MATH数据集的不同类别中,难度为5级的所有问题上的准确率如下所示:

结果 我们发现,与基本提示相比,使用Python在PoT或PS策略的背景下,可以将GPT-4的整体准确性提高约10%。这种增加主要出现在涉及更多数值操作的类别中,例如计数与概率、数论,以及更复杂的类别,如中级代数和预微积分。

对于代数和初代数等类别,PoT和PS的改进很小,甚至在某些情况下,准确性还会下降。然而,与PoT和PS相比,MathChat能够将总体准确性提高约6%,在所有类别中表现出竞争力。值得注意的是,MathChat在代数类别中的准确性比其他方法提高了约15%。需要注意的是,中级代数和预微积分等类别对所有方法来说仍然具有挑战性,只有约20%的问题能够准确解决。

实验代码可以在这个仓库中找到。我们现在提供了使用AutoGen中的交互式代理实现的MathChat。请参考这个notebook了解示例用法。

未来的方向

尽管MathChat相对于以前的方法有所改进,但结果显示,对于最近强大的LLM(如GPT-4)来说,复杂的数学问题仍然具有挑战性,即使在外部工具的帮助下也是如此。

可以进行进一步的工作来改进这个框架或数学问题的解决方法:

  • 尽管使模型能够使用Python等工具可以减少计算错误,但LLM仍然容易出现逻辑错误。采用自一致性(对最终答案进行多次采样并进行多数投票)或自验证(使用另一个LLM实例来检查答案是否正确)等方法可能会提高性能。
  • 有时,LLM能否解决问题取决于它使用的计划。某些计划需要较少的计算和逻辑推理,从而减少了错误的可能性。
  • MathChat有潜力成为一个协作系统,可以帮助用户解决数学问题。这个系统可以让用户更多地参与到解决问题的过程中,从而可能提高学习效果。

进一步阅读

您是否正在开发涉及数学问题解决的应用程序?您是否希望在LLM为基础的代理在数学问题解决中的应用方面获得更多的研究或支持?请加入我们的Discord服务器进行讨论。

· 13 min read
Chi Wang

使用 GPT-3.5 和 GPT-4 的自适应方法在编码成功率和推理成本方面优于 GPT-4

TL;DR:

  • 使用 HumanEval 基准测试的案例研究表明,使用多个 GPT 模型的自适应方法在编码方面可以实现更高的准确性(从 68% 提高到 90%),同时推理成本降低了 18%,比单独使用 GPT-4 更加高效。

GPT-4 是基础模型能力的重大升级,例如在代码和数学方面,但使用 GPT-4 的每个令牌的价格要比 GPT-3.5-Turbo 高出多达 10 倍以上。在由 OpenAI 开发的代码补全基准测试 HumanEval 上,GPT-4 可以成功解决 68% 的任务,而 GPT-3.5-Turbo 只能解决 46% 的任务。通过生成多个响应或进行多次调用,可以进一步提高 GPT-4 的成功率。然而,这将进一步增加成本,而已经接近使用 GPT-3.5-Turbo 的 20 倍,并且具有更受限制的 API 调用速率限制。我们能否以更少的成本实现更多的效果呢?

在本博客文章中,我们将探索一种创造性的、自适应的 GPT 模型使用方法,从而实现了一次巨大的飞跃。

观察结果

  • GPT-3.5-Turbo 已经可以解决 40%-50% 的任务。对于这些任务,如果我们从不使用 GPT-4,我们可以节省近 40-50% 的成本。
  • 如果我们使用节省下来的成本,为剩下的未解决任务使用 GPT-4 生成更多的响应,有可能解决其中的一些任务,同时保持平均成本较低。

利用这些观察结果的障碍在于我们不知道哪些任务可以由更便宜的模型解决,哪些任务可以由更昂贵的模型解决,以及哪些任务可以通过支付更多的费用来解决。

为了克服这个障碍,我们可能希望预测哪个任务需要使用哪个模型来解决,以及每个任务需要多少个响应。让我们看一个代码补全任务的例子:

def vowels_count(s):
"""编写一个函数 vowels_count,该函数接受一个表示单词的字符串作为输入,并返回字符串中元音字母的数量。
在这种情况下,元音字母是 'a'、'e'、'i'、'o'、'u'。这里,'y' 也是元音字母,但只有当它位于给定单词的末尾时才是。

示例:
>>> vowels_count("abcde")
2
>>> vowels_count("ACEDY")
3
"""

我们能否预测 GPT-3.5-Turbo 是否能够解决这个任务,或者我们需要使用 GPT-4?我最初的猜测是 GPT-3.5-Turbo 可以做对,因为指令相当简单。然而,事实证明,如果我们只给它一次机会,GPT-3.5-Turbo 并不总是能够正确解决。如何在不实际尝试的情况下预测性能并不明显(但这是一个有趣的研究问题!)。

我们还能做什么呢?我们注意到: 验证给定解决方案比从头开始找到正确解决方案要“容易”。 在文档字符串中提供了一些简单的示例测试用例。如果我们已经有了模型生成的响应,我们可以使用这些测试用例来过滤错误的实现,并使用更强大的模型或生成更多的响应,直到结果通过示例测试用例。此外,可以通过询问GPT-3.5-Turbo从文档字符串中给出的示例生成断言语句(一个更简单的任务,我们可以押注)并执行代码来自动化此步骤。

解决方案

结合这些观察结果,我们可以设计一个具有两个直观思路的解决方案:

  • 利用自动生成的反馈,即代码执行结果,来过滤响应。
  • 逐个尝试推理配置,直到找到一个能通过过滤的响应。

设计

这个解决方案在不知道或预测哪个任务适合哪个配置的情况下,能够自适应地工作。它只是逐个尝试多个配置,从最便宜的配置开始。注意,一个配置可以生成多个响应(通过将推理参数n设置为大于1)。不同的配置可以使用相同的模型和不同的推理参数,如n和temperature。每个任务只返回和评估一个响应。

autogen中提供了这个解决方案的实现。它使用以下配置序列:

  1. GPT-3.5-Turbo,n=1,temperature=0
  2. GPT-3.5-Turbo,n=7,temperature=1,stop=["\nclass", "\ndef", "\nif", "\nprint"]
  3. GPT-4,n=1,temperature=0
  4. GPT-4,n=2,temperature=1,stop=["\nclass", "\ndef", "\nif", "\nprint"]
  5. GPT-4,n=1,temperature=1,stop=["\nclass", "\ndef", "\nif", "\nprint"]

实验结果

本博文的第一个图表显示了自适应解决方案与默认的GPT-4相比的成功率和平均推理成本。推理成本包括我们解决方案中生成断言的成本。生成的断言并不总是正确的,通过/未通过生成的断言的程序也不总是正确/错误的。尽管如此,自适应解决方案可以将成功率(在文献中称为pass@1)从68%提高到90%,同时将成本降低了18%。

以下是由组合中的不同配置解决的一些函数定义示例。

  1. 由GPT-3.5-Turbo,n=1,temperature=0解决
def compare(game, guess):
"""我想我们都记得那种期待已久的事件结果终于揭晓的感觉。那一刻你所拥有的感受和想法绝对值得记录下来并进行比较。
你的任务是确定一个人是否正确猜测了一系列比赛的结果。
给定两个长度相等的得分和猜测的数组,每个索引表示一场比赛。
返回一个相同长度的数组,表示每个猜测离实际结果有多远。如果猜测正确,则值为0,否则值为猜测值与实际得分之间的绝对差值。

示例:

compare([1,2,3,4,5,1],[1,2,3,4,2,-2]) -> [0,0,0,0,3,3]
compare([0,5,0,0,0,4],[4,1,1,0,0,-2]) -> [4,4,1,0,0,6]
"""
  1. 使用 GPT-3.5-Turbo,n=7,temperature=1,stop=["\nclass", "\ndef", "\nif", "\nprint"],解决了之前提出的 vowels_count 函数。

  2. 使用 GPT-4,n=1,temperature=0,解决了以下问题:

def string_xor(a: str, b: str) -> str:
""" 输入是两个字符串 a 和 b,只包含 1 和 0。
对这些输入进行二进制异或运算,并将结果作为字符串返回。
>>> string_xor('010', '110')
'100'
"""
  1. 使用 GPT-4,n=2,temperature=1,stop=["\nclass", "\ndef", "\nif", "\nprint"],解决了以下问题:
def is_palindrome(string: str) -> bool:
""" 检测给定的字符串是否是回文 """
return string == string[::-1]


def make_palindrome(string: str) -> str:
""" 找到以给定字符串开头的最短回文串。
算法思想很简单:
- 找到给定字符串的最长后缀,该后缀是回文的。
- 将回文后缀之前的字符串前缀的反转附加到字符串的末尾。
>>> make_palindrome('')
''
>>> make_palindrome('cat')
'catac'
>>> make_palindrome('cata')
'catac'
"""
  1. 使用 GPT-4,n=1,temperature=1,stop=["\nclass", "\ndef", "\nif", "\nprint"],解决了以下问题:
def sort_array(arr):
"""
在这个 Kata 中,你需要根据二进制表示中 1 的个数按升序对非负整数数组进行排序。
对于相同数量的 1,根据十进制值进行排序。

必须按照以下方式实现:
>>> sort_array([1, 5, 2, 3, 4]) == [1, 2, 3, 4, 5]
>>> sort_array([-2, -3, -4, -5, -6]) == [-6, -5, -4, -3, -2]
>>> sort_array([1, 0, 2, 3, 4]) [0, 1, 2, 3, 4]
"""

最后一个问题是一个示例,原始定义中的示例测试用例是错误的。这会误导自适应解决方案,因为正确的实现被视为错误,并进行了更多的尝试。序列中的最后一个配置返回了正确的实现,即使它没有通过自动生成的断言。这个例子说明了以下几点:

  • 我们的自适应解决方案具有一定的容错能力。
  • 如果使用正确的示例测试用例,自适应解决方案的成功率和推理成本可以进一步提高。

值得注意的是,减少的推理成本是对所有任务的摊销成本。对于每个单独的任务,成本可能比直接使用 GPT-4 要大或者要小。这是自适应解决方案的本质:对于困难的任务,成本通常比简单任务要大。

可以在以下链接找到一个运行此实验的示例笔记本:https://github.com/microsoft/FLAML/blob/v1.2.1/notebook/research/autogen_code.ipynb。该实验是在 AutoGen 是 FLAML 的子包时运行的。

讨论

我们的解决方案非常简单,使用 autogen 中提供的通用接口实现,但结果令人鼓舞。 虽然生成断言的具体方法因应用而异,但在LLM操作中的主要思想是通用的:

  • 生成多个响应供选择 - 当选择一个好的响应相对容易,而一次生成一个好的响应相对困难时,这一点尤为有用。
  • 考虑多个配置来生成响应 - 当:
    • 模型和其他推理参数的选择影响效用成本权衡时;或者
    • 不同的配置具有互补效果时,这一点尤为有用。

先前的博客文章 提供了证据,证明这些思想在解决数学问题时也是相关的。 autogen使用一种名为EcoOptiGen的技术来支持推理参数调优和模型选择。

在研究和开发中有许多扩展方向:

  • 推广提供反馈的方式。
  • 自动化配置优化过程。
  • 为不同应用构建自适应代理。

您是否认为这种方法适用于您的用例?您是否有关于LLM应用的其他挑战要分享?您是否希望看到更多关于LLM优化或自动化的支持或研究?请加入我们的Discord服务器进行讨论。

进一步阅读

· 8 min read
Chi Wang

二级代数

简介:

  • 仅通过调整推理参数,如模型、回答数量、温度等,而不改变任何模型权重或提示,高中数学竞赛问题中未调整的gpt-4的基准准确率可以提高20%。
  • 对于简单问题,调整后的gpt-3.5-turbo模型在准确性(例如90%对70%)和成本效益方面远远优于未调整的gpt-4。对于困难问题,调整后的gpt-4比未调整的gpt-4更准确(例如35%对20%)且成本更低。
  • AutoGen可以帮助LLM应用中的模型选择、参数调整和节省成本。

大型语言模型(LLM)是强大的工具,可以为各种应用生成自然语言文本,例如聊天机器人、摘要、翻译等。GPT-4是目前世界上最先进的LLM。模型选择是否无关紧要?推理参数又如何?

在本篇博文中,我们将使用一个关于MATH的案例研究,探讨模型和推理参数在LLM应用中的重要性。MATH是一个用于评估LLM在高级数学问题解决上的基准测试。MATH包含来自AMC-10、AMC-12和AIME的1.2万个数学竞赛问题。每个问题都附带有逐步解决方案。

我们将使用AutoGen来自动找到给定任务和数据集上LLM的最佳模型和推理参数,同时考虑推理预算,使用一种新颖的低成本搜索和修剪策略。AutoGen目前支持OpenAI的所有LLM,如GPT-3.5和GPT-4。

我们将使用AutoGen进行模型选择和推理参数调整。然后,我们将与未调整的gpt-4比较在解决代数问题上的性能和推理成本。我们还将分析不同难度级别对结果的影响。

实验设置

我们使用AutoGen在目标推理预算为每个实例0.02美元的情况下,在以下模型之间进行选择:

  • gpt-3.5-turbo,一种相对便宜的模型,用于推动流行的ChatGPT应用
  • gpt-4,代价是gpt-3.5-turbo的10倍以上的最先进LLM

我们使用训练集中的20个示例来调整模型,将问题陈述作为输入,生成解决方案作为输出。我们使用以下推理参数:

  • 温度:控制输出文本的随机性的参数。较高的温度意味着更多的多样性但较少的连贯性。我们在[0, 1]的范围内搜索最佳温度。
  • top_p: 控制输出标记的概率质量的参数。只有累积概率小于等于 top-p 的标记才会被考虑。较低的 top-p 值意味着更多的多样性但较少的连贯性。我们在 [0, 1] 的范围内搜索最佳的 top-p 值。
  • max_tokens: 每个输出可以生成的最大标记数。我们在 [50, 1000] 的范围内搜索最佳的最大长度。
  • n: 要生成的响应数量。我们在 [1, 100] 的范围内搜索最佳的 n 值。
  • prompt: 我们使用模板:“{problem} 仔细解决问题。尽量简化你的答案。将最终答案放在 \boxed{{}} 中。”其中 {problem} 将被数学问题实例替换。

在这个实验中,当 n > 1 时,我们在所有响应中找到得票最高的答案,然后将其选为最终答案与真实答案进行比较。例如,如果 n = 5,其中 3 个响应包含最终答案 301,而 2 个响应包含最终答案 159,我们选择 301 作为最终答案。这有助于解决由于随机性而导致的潜在错误。我们使用平均准确率和平均推理成本作为评估数据集性能的指标。特定实例的推理成本由每 1K 标记的价格和消耗的标记数来衡量。

实验结果

本博文的第一个图显示了在二级代数测试集上每个配置的平均准确率和平均推理成本。

令人惊讶的是,调整后的 gpt-3.5-turbo 模型被选为更好的模型,并且在准确率上远远优于未调整的 gpt-4(92% vs. 70%),而推理预算相等或高出 2.5 倍。 在三级代数测试集上也可以得出同样的观察结果。

level 3 algebra

然而,在四级代数中选择的模型发生了变化。

level 4 algebra

这次选择了 gpt-4 作为最佳模型。调整后的 gpt-4 在准确率上比未调整的 gpt-4 高得多(56% vs. 44%),成本更低。 在五级代数中的结果类似。

level 5 algebra

我们可以看到 AutoGen 对于每个特定级别的子集找到了不同的最佳模型和推理参数,这表明这些参数在成本敏感的 LLM 应用中很重要,需要进行仔细调整或适应。

可以在以下链接找到一个运行这些实验的示例笔记本:https://github.com/microsoft/FLAML/blob/v1.2.1/notebook/autogen_chatgpt.ipynb。这些实验是在 AutoGen 是 FLAML 的一个子包时运行的。

分析与讨论

虽然 gpt-3.5-turbo 在相同推理预算下在相对简单的代数问题中展示了与投票答案相竞争的准确性,但对于最困难的问题来说,gpt-4 是更好的选择。一般来说,通过参数调整和模型选择,我们可以确定在更具挑战性的任务中节省昂贵模型的机会,并提高预算受限系统的整体效果。

还有许多其他解决数学问题的替代方法,我们在本博客文章中没有涵盖。当推理参数以外有选择时,可以通过 flaml.tune 进行通常的调整。

对于模型选择、参数调整和成本节约的需求并不局限于数学问题。Auto-GPT 项目就是一个例子,高成本很容易阻止完成通用复杂任务,因为它需要进行多次 LLM 推理调用。

进一步阅读

你有关于 LLM 应用的经验要分享吗?你是否希望看到更多关于 LLM 优化或自动化的支持或研究?请加入我们的 Discord 服务器进行讨论。